使用绑定以声明方式在WPF中指定和显示DataGrid的列?

时间:2009-12-07 21:56:53

标签: .net wpf xaml datagrid binding

有没有办法以声明方式使用绑定指定DataGrid列? (并使用此绑定设置列的属性?) 理想情况下,我会将一个对象列表(例如行)数据绑定到ItemsSource,它们的一个属性将是一个字典(或某个类或其他任何对象的列表),其名称和值。我希望DataGrid自动创建这些额外的列,而不需要一些代码。这甚至可能吗?或者你会如何解决这个问题呢?

保存额外值的数组可能随时间而变化,但对于列表中的所有项目都是相同的。

可以(并且干净)为DataGrid提供一个不同的列表,只是为了从中创建列。但为此我需要像ColumnsSource之类的东西......

我唯一想到的就是创建DataGrid的子类......

有什么想法吗?

编辑: 重点是在没有任何代码的情况下实现这一目标......

3 个答案:

答案 0 :(得分:1)

在您的XAML中,将您的数据网格绑定到具有属性的某个类的对象的ObservableCollection。

XAML:

<WpfToolkit:DataGrid
        x:Name="MyDataGrid"
        ItemsSource="{Binding Path=Collection}"
        HorizontalScrollBarVisibility="Hidden" SelectionMode="Extended"
        CanUserAddRows="False" CanUserDeleteRows="False"
        CanUserResizeRows="False" CanUserSortColumns="False"
        AutoGenerateColumns="False"
        RowHeaderWidth="25" RowHeight="25"/>

接下来,您可以在C#/ VBA中以编程方式创建列,并将每个列绑定到ObservableCollection包含其对象的类的属性。通过添加类的对象,您将向数据网格添加行。换句话说,ObservableCollection中类的每个对象都是一行,类的属性将是列。

以下是如何以编程方式绑定列的示例... C#:

ObservableCollection<IData> datagridData = new ObservableCollection< IData >();
Binding items = new Binding();
PropertyPath path = new PropertyPath("Name"); // 'Name' is actually the name of the variable representing the property
items.Path = path;

MyDataGrid.Columns.Add(new DataGridTextColumn()
{
   Header = "Names",
   Width =  275,
   Binding = items
});
//repeat the creation of columns
//...
//- Add some objects to the ObservableCollection
//- Then bind the ItemsSource of the datagrid to the ObservableCollection
datagridData .Add(new Data("Bob", string.Empty));
MyDataGrid.DataContext = new DataModel{ MyData = datagridData };

*编辑: 对于那个很抱歉!以下是如何在XAML中完全实现相同的目的:

<WpfToolkit:DataGrid
        x:Name="MyDataGrid"
        ItemsSource="{Binding Path=Collection}"
        HorizontalScrollBarVisibility="Hidden" SelectionMode="Extended"
        CanUserAddRows="False" CanUserDeleteRows="False"
        CanUserResizeRows="False" CanUserSortColumns="False"
        AutoGenerateColumns="False"
        RowHeaderWidth="25" RowHeight="25">

             <WpfToolkit:DataGridTextColumn
                        Header="Names" Width="2*"
                        Binding="{Binding Path=Name}"/>
             <WpfToolkit:DataGridTextColumn
                        Header="Names" Width="2*"
                        Binding="{Binding Path=Age}"/>

        </WpfToolkit:DataGrid.Columns>
</WpfToolkit:DataGrid>

编辑2:这是ObservableCollection和类的代码在C#中的样子:

public class DataModel
    {
        public ObservableCollection<IData> MyData{ get; set; }
    }

public interface IData
    {
        string Name{ get; set; }
        string Age{ get; set; }
    }

public class Data : IData
    {
        public Data(string name, string age)
        {
            Name= name;
            Age= age;
        }

        public string Name{ get; set; }
        public string Age{ get; set; }
    }

答案 1 :(得分:1)

冒着引起争议的风险......

我认为这是一个示例,其中View确实需要一些代码“提升”,并且“无代码隐藏”指南可以放在一边 - 只要您记得将您的问题分开

过去,我通过从ViewModel中获取相关数据,并在代码隐藏中编写类似于Partial的答案的“BuildDataGrid”方法来动态创建DataGrid控件。 我认为这是合理的,因为代码纯粹关注补充View,并且我没有通过实现业务规则来混淆问题 - 它只是将列放在一起,并在适当时创建了列Bindings。

但是如果保持代码隐藏更为重要,那么我建议您最初想到创建用户控件并使用DP来“控制”子类。

答案 2 :(得分:0)

我认为你必须继承网格。列不是可绑定的属性。如果你不能绑定它,你就无法在xaml中动态地摆弄它。

至于使用项目来创建列,这是否意味着如果网格中没有项目就没有列?

如果您的网格的子类具有可绑定的columns属性,则动态更改列的位置将位于视图模型中。