我想为DataGrid
实现自定义添加行按钮(这是一个很长的故事)。我在模板中添加了按钮,并定义了附加属性,我可以点击按钮。但我不能以通用方式添加新行 - 不是指定类型。我知道我可以在ViewModel
中做类似的事情,但我希望在模板和附加属性中执行此操作。这是我的尝试;有没有想过要完成这个?
XAML:
<Style x:Key="{x:Type DataGrid}" TargetType="{x:Type DataGrid}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGrid}">
<Border x:Name="border">
<ScrollViewer x:Name="DG_ScrollViewer" Focusable="false">
<ScrollViewer.Template>
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Button Focusable="false"
Command="{x:Static DataGrid.SelectAllCommand}" />
<DataGridColumnHeadersPresenter
x:Name="PART_ColumnHeadersPresenter"
Grid.Column="1" />
<Grid Grid.ColumnSpan="2" Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="22" />
</Grid.RowDefinitions>
<ScrollContentPresenter
x:Name="PART_ScrollContentPresenter" />
<!-- THIS IS MY CUSTOM BUTTON TO ADD NEW ROW -->
<Button x:Name="PART_AddRowButton"
Content="Add"/>
</Grid>
<ScrollBar x:Name="PART_VerticalScrollBar"/>
<Grid Grid.Column="1" Grid.Row="2">
<ScrollBar x:Name="PART_HorizontalScrollBar"/>
</Grid>
</Grid>
</ControlTemplate>
</ScrollViewer.Template>
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
C#:
public class DataGridHelper {
public static readonly DependencyProperty CanUserAddRowsProperty
= DependencyProperty.RegisterAttached(
"CanUserAddRows", typeof(bool), typeof(DataGridHelper),
new FrameworkPropertyMetadata(default(bool), CanUserAddRowsChanged));
[AttachedPropertyBrowsableForType(typeof(DataGrid))]
public static bool GetCanUserAddRows(DependencyObject obj) {
return (bool)obj.GetValue(CanUserAddRowsProperty);
}
[AttachedPropertyBrowsableForType(typeof(DataGrid))]
public static void SetCanUserAddRows(DependencyObject obj, bool value) {
obj.SetValue(CanUserAddRowsProperty, value);
}
private static void CanUserAddRowsChanged(
DependencyObject d,
DependencyPropertyChangedEventArgs e) {
var dataGrid = d as DataGrid;
if (dataGrid == null)
return;
bool oldValue = (bool)e.OldValue,
newValue = (bool)e.NewValue;
if (newValue == oldValue)
return;
if (newValue) {
dataGrid.Loaded += CanUserAddRowsDataGridLoaded;
} else {
dataGrid.Loaded -= CanUserAddRowsDataGridLoaded;
}
}
private static void CanUserAddRowsDataGridLoaded(object sender, RoutedEventArgs e) {
var dataGrid = sender as DataGrid;
if (dataGrid == null)
return;
if (dataGrid.Style == null)
return;
var rootTemplate = dataGrid.Template;
if (rootTemplate == null)
return;
var scroll = rootTemplate.FindName("DG_ScrollViewer", dataGrid) as ScrollViewer;
if (scroll == null)
return;
var scrollTemplate = scroll.Template;
if (scrollTemplate == null)
return;
var button = scrollTemplate.FindName("PART_AddRowButton", scroll) as ButtonBase;
if (button == null)
return;
if (GetCanUserAddRows(dataGrid)) {
button.Click += AddRowClicked;
} else {
button.Click -= AddRowClicked;
}
}
private static void AddRowClicked(object sender, RoutedEventArgs e) {
var button = ((ButtonBase)sender);
var parent = VisualTreeHelper.GetParent(button);
while (!(parent is DataGrid))
parent = VisualTreeHelper.GetParent(parent);
var source = ((DataGrid)parent).Items.Add(...) // now what???
}
}
嗯,正如您所看到的,点击按钮后我可以访问DataGrid
;但是下一步是什么?如何强制DataGrid
显示NewItemPlaceHolder
?
答案 0 :(得分:0)
通常在WPF中,我们将数据对象的集合(最好是支持更改通知的集合,如ObservableCollection
)绑定到UI控件。我们不是将新项添加到UI控件,而是将代码添加到代码隐藏/视图模型中的集合中。只要集合支持更改通知,UI控件就会自动更新。
因此,要向DataGrid
添加新行,您需要在集合中添加新项目:
dataCollection.Add(new DataType());
您应该能够使用以下内容访问AttachedProperty
中的数据绑定集合。
var dataCollection = (DataCollectionType)dataGrid.ItemsSource;
我相信你也可以使用:
dataGrid.Items.Add(new DataType());
虽然不推荐这种方法。