我可以在 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&lt;DataGridColumn&gt; (虽然你在技术上只说列,但我喜欢自己完整,所以我也会为行做一个)然后将它们添加到你可以引用的地方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的主要内容,如果未能解决你的问题,请参考以下文章

EasyUI之datagrid的使用

WPF Datagrid行上下文菜单-禁用菜单项[关闭]

在 Winforms 项目中使用 DataGrid 中的复选框列

动态设置 dojox.grid.datagrid 标题列宽

wpf datagrid怎么得到第一项焦点?然后在方向键上下移动

怎么把数据库中的数据通过jquery easyui datagrid进行绑定绑定