AutoGenerateColumns = False时WPF DataGrid ItemsSource中项的形状

时间:2011-04-13 21:09:21

标签: wpf datagrid

当我使用WPF DataGrid时(我假设SL版本的工作方式类似),并且我在运行时指定列(即它们在编译时不可知,因此通过Reflection自动生成列不起作用) )

如何提供项目以便它们在网格中正确显示?换句话说,给定以下DataGrid:

<DataGrid x:Name="dataGrid" AutoGenerateColumns="False">
  <DataGrid.Columns>
    <DataGridTextColumn Header="Foo"/>
    <DataGridTextColumn Header="Bar"/>
    <DataGridTextColumn Header="Baz"/>
  </DataGrid.Columns>
</DataGrid>

我尝试了以下内容:

dataGrid.Items.Add(new[] {"a1", "a2", "a3"});
dataGrid.Items.Add(new[] {"b1", "b2", "b3"});

dataGrid.Items.Add(new Dictionary<string, string>() {
    {"Foo", "a1"},
    {"Bar", "a2"},
    {"Baz", "a3"},
});

dataGrid.Items.Add(new Dictionary<string, string>() {
    {"Foo", "b1"},
    {"Bar", "b2"},
    {"Baz", "b3"},
});

请注意,尽管在我的示例中列是在Xaml中定义的并且是静态的,但对于我的应用程序,它们在Xaml中并且将在运行时生成(所以我不能只是创建一个具有属性“Foo”,“Bar”,“Baz”)

的类

1 个答案:

答案 0 :(得分:1)

您最好的选择可能是以实现ICustomTypeDescriptor的类的形式展示您的项目。这样,您可以根据需要动态添加属性,DataGrid会自动选择它们(如果您将AutoGenerateColumns设置回true)。

另一种选择是使用ExpandoObject,但DataGrid将无法自动检测属性。但是,如果您手动创建列,则可以使用它:

dg.Columns.Add(new DataGridTextColumn { Header = "Foo", Binding = new Binding("Foo") });
dg.Columns.Add(new DataGridTextColumn { Header = "Bar", Binding = new Binding("Bar") });
dg.Columns.Add(new DataGridTextColumn { Header = "Baz", Binding = new Binding("Baz") });


dynamic x = new ExpandoObject();
x.Foo = 42;
x.Bar = "Hello";
x.Baz = DateTime.Today;
dg.Items.Add(x);

x = new ExpandoObject();
x.Foo = 0;
x.Bar = "zzz";
x.Baz = DateTime.MinValue;
dg.Items.Add(x);

编辑:实际上,我意识到你可能在编译时不知道属性的名称,所以ExpandoObject对你不起作用。相反,您可以使用我在this blog post中发布的示例类,并添加方法以按名称访问属性:

public class MyDynamicObject : DynamicObject
{
    private Dictionary<string, object> _properties = new Dictionary<string, object>();

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        return _properties.TryGetValue(binder.Name, out result);
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        _properties[binder.Name] = value;
        return true;
    }

    public void SetProperty(string name, object value)
    {
        _properties[name] = value;
    }

    public object GetProperty(string name)
    {
        return _properties[name];
    }
}

EDIT2:我刚刚意识到我忘记了另一个非常简单的方法:使用DataTable。它很容易设置,DataGrid将能够自动生成列。