我可以在 DataGrid 表之间共享 DataGrid.Columns
Posted
技术标签:
【中文标题】我可以在 DataGrid 表之间共享 DataGrid.Columns【英文标题】:Can I share DataGrid.Columns amongst DataGrid tables 【发布时间】:2011-05-05 01:21:15 【问题描述】:我有 3 个共享相同数据类型的数据网格。我想配置一次列绑定,让 3 个数据网格共享资源。
例如
<DataGrid Grid.Row="1" x:Name="primaryDG" ItemsSource="Binding Path=dgSource AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Width="Auto" Header="Column 1" Binding="Binding Path=Col1"/>
<DataGridTextColumn Width="Auto" Header="Column 2" Binding="Binding Path=Col2"/>
<DataGridTextColumn Width="Auto" Header="Column 3" Binding="Binding Path=Col3"/>
<DataGridTextColumn Width="Auto" Header="Column 4" Binding="Binding Path=Col4"/>
</DataGrid.Columns>
</DataGrid>
有没有办法为每个 DataGrid 设置 ItemsSource,然后使用 datatemplate 或 controltemplate 来获取列?
【问题讨论】:
类似问题,有用的答案:***.com/questions/5716123/… 【参考方案1】:是的……两种方式。您可以简单地为DataGrid
添加一个样式,设置这样的列...
<Style x:Key="MyColumnDefsStyle" x:Shared="True" TargetType="DataGrid">
<Setter Property="Columns">
<Setter.Value>
<DataGridTextColumn Width="Auto" Header="Column 1" Binding="Binding Path=Col1"/>
<DataGridTextColumn Width="Auto" Header="Column 2" Binding="Binding Path=Col2"/>
<DataGridTextColumn Width="Auto" Header="Column 3" Binding="Binding Path=Col3"/>
<DataGridTextColumn Width="Auto" Header="Column 4" Binding="Binding Path=Col4"/>
</Setter.Value>
</Setter>
</Style>
<DataGrid Style="StaticResource MyColumnDefsStyle" ItemsSource="Binding Foo1" />
<DataGrid Style="StaticResource MyColumnDefsStyle" ItemsSource="Binding Foo2" />
<DataGrid Style="StaticResource MyColumnDefsStyle" ItemsSource="Binding Foo3" />
这可行,但如果您将其应用于多个自己可能已经在使用一种样式的网格,则会出现问题。
在这种情况下,另一种更灵活的方式效果更好。然而,这需要创建一个 XAML 友好的类来表示 ObservableCollection<DataGridColumn>
(虽然你在技术上只说列,但我喜欢自己完整,所以我也会为行做一个)然后将它们添加到你可以引用的地方XAML 命名空间。 (我打电话给我的xmlns:dge
'DataGridEnhancements')然后你像这样使用它:
在某处的代码中(我会让它在应用程序范围内可访问)...
public class DataGridRowsCollection : ObservableCollection<DataGridRow>
public class DataGridColumnsCollection : ObservableCollection<DataGridColumn>
然后在资源中...
<dge:DataGridColumnsCollection x:Key="MyColumnDefs" x:Shared="True">
<DataGridTextColumn Width="Auto" Header="Column 1" Binding="Binding Path=Col1"/>
<DataGridTextColumn Width="Auto" Header="Column 2" Binding="Binding Path=Col2"/>
<DataGridTextColumn Width="Auto" Header="Column 3" Binding="Binding Path=Col3"/>
<DataGridTextColumn Width="Auto" Header="Column 4" Binding="Binding Path=Col4"/>
</dge:DataGridColumnsCollection>
最后在 XAML 中...
<DataGrid Columns="StaticResource MyColumnDefs" ItemsSource="Binding Foo1" />
<DataGrid Columns="StaticResource MyColumnDefs" ItemsSource="Binding Foo2" />
<DataGrid Columns="StaticResource MyColumnDefs" ItemsSource="Binding Foo3" />
HTH,
标记
编辑:
由于您无法设置 DataGrid.Columns
属性,因此您需要增强您的 DataGridView
(如 cmets 中所述)。这是EnhancedDataGrid
的代码:
public class EnhancedDataGrid : DataGrid
//the dependency property for 'setting' our columns
public static DependencyProperty SetColumnsProperty = DependencyProperty.Register(
"SetColumns",
typeof (ObservableCollection<DataGridColumn>),
typeof (EnhancedDataGrid),
new FrameworkPropertyMetadata
DefaultValue = new ObservableCollection<DataGridColumn>(),
PropertyChangedCallback = EnhancedDataGrid.SetColumnsChanged,
AffectsRender = true,
AffectsMeasure = true,
AffectsParentMeasure = true,
IsAnimationProhibited = true,
DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
);
//callback to reset the columns when our dependency property changes
private static void SetColumnsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
var datagrid = (DataGrid) d;
datagrid.Columns.Clear();
foreach (var column in (ObservableCollection<DataGridColumn>)e.NewValue)
datagrid.Columns.Add(column);
//The dependency property wrapper (so that you can consume it inside your xaml)
public ObservableCollection<DataGridColumn> SetColumns
get return (ObservableCollection<DataGridColumn>) this.GetValue(EnhancedDataGrid.SetColumnsProperty);
set this.SetValue(EnhancedDataGrid.SetColumnsProperty, value);
现在您可以使用在您的 CustomControl 中创建的 SetColumns 依赖属性设置列:
<custom:EnhancedDataGrid SetColumns="StaticResource MyColumnDefs" ItemsSource="Binding Foo1" />
<custom:EnhancedDataGrid SetColumns="StaticResource MyColumnDefs" ItemsSource="Binding Foo2" />
<custom:EnhancedDataGrid SetColumns="StaticResource MyColumnDefs" ItemsSource="Binding Foo3" />
【讨论】:
真的有用吗? Columns 属性没有设置器:msdn.microsoft.com/en-us/library/… 糟糕!我想你是正确的。我们的代码有效,因为我们使用了一个名为 EnhancedDataGrid 的自定义子类来处理它。它添加了 setter,但实际上只是移动了孩子们。例如,我只是将类名从我们的子类更改为 DataGrid。谢谢你说出来。最简单的方法是添加第二个 Collection 属性,并在内部绑定它们的内容。此代码在网格内只有微小的变化。 感谢不错的解决方案。你能告诉我如何根据我的视图模型上的某些属性设置网格“样式”吗?我基于相同的数据有不同的布局 @MarqueIV 我已经编辑了您的答案,为自定义控件提供了重置属性DataGrid.Columns
的依赖属性。
您可以使用附加属性而不是自定义网格。 ***.com/a/4379965/991267【参考方案2】:
此答案基于 MarquelV 的解决方案。在他的回答中(以及在 cmets 中),他提到了一个名为 EnhancedDataGrid
的自定义控件,他在其中提供了 set DataGrid.Columns
属性的逻辑。这是EnhancedDataGrid
的代码:
public class EnhancedDataGrid : DataGrid
//the dependency property for 'setting' our columns
public static DependencyProperty SetColumnsProperty = DependencyProperty.Register(
"SetColumns",
typeof (ObservableCollection<DataGridColumn>),
typeof (EnhancedDataGrid),
new FrameworkPropertyMetadata
DefaultValue = new ObservableCollection<DataGridColumn>(),
PropertyChangedCallback = EnhancedDataGrid.SetColumnsChanged,
AffectsRender = true,
AffectsMeasure = true,
AffectsParentMeasure = true,
IsAnimationProhibited = true,
DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
);
//callback to reset the columns when our dependency property changes
private static void SetColumnsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
var datagrid = (DataGrid) d;
datagrid.Columns.Clear();
foreach (var column in (ObservableCollection<DataGridColumn>)e.NewValue)
datagrid.Columns.Add(column);
//The dependency property wrapper (so that you can consume it inside your xaml)
public ObservableCollection<DataGridColumn> SetColumns
get return (ObservableCollection<DataGridColumn>) this.GetValue(EnhancedDataGrid.SetColumnsProperty);
set this.SetValue(EnhancedDataGrid.SetColumnsProperty, value);
现在您可以使用在您的 CustomControl 中创建的 SetColumns 依赖属性设置列:
<custom:EnhancedDataGrid SetColumns="StaticResource MyColumnDefs" ItemsSource="Binding Foo1" />
<custom:EnhancedDataGrid SetColumns="StaticResource MyColumnDefs" ItemsSource="Binding Foo2" />
<custom:EnhancedDataGrid SetColumns="StaticResource MyColumnDefs" ItemsSource="Binding Foo3" />
【讨论】:
【参考方案3】:您可以创建一个自定义控件来包装数据网格并将数据传递给它。该控件将在网格上设置数据。
【讨论】:
这仅适用于所有迭代之间的整个网格相同的情况,这可能是也可能不是。另外,它也限制了使用控件模板或其他样式设置它们的样式,因为您已将其包装在 UserControl 中。 @Queso 专门询问了列,这就是为什么我建议上述解决方案的原因,该解决方案仅针对该列,并且可以在您使用网格的任何地方使用,包括在 UserControl 内。以上是关于我可以在 DataGrid 表之间共享 DataGrid.Columns的主要内容,如果未能解决你的问题,请参考以下文章
在 Winforms 项目中使用 DataGrid 中的复选框列