Silverlight DataGrid - 绑定到对象集合的集合

时间:2010-01-08 07:52:30

标签: silverlight data-binding datagrid binding

问题:我试图显示的数据本质上是一些对象集合的集合。因此行可以是任何数字,对于数据网格是正常的,并且列也是任何数字。这对于数据网格来说并不常见。通常,您有一定数量的列,并且您的行会有所不同。 datagrid单元格可以是字符串,也可以通过组合框更改值。

尝试的解决方案:我尝试动态地向数据网格添加列,虽然这很好用(在代码隐藏中添加它们)但我遇到的真正问题是如何绑定到底层对象。数据是动态构建的,我尝试了几种格式。我尝试了一组Arrays,还有ObservableCollection的ObservableCollection。我可以绑定到对象,但由于Silverlight中的Bindings必须绑定到属性,我无法想出以这种方式呈现数据的解决方案。

我的解决方案是以更传统的方式显示数据,包括列表和数据网格。当您在列表中选择一个项目时,它会重新填充数据网格中的数据以显示对象。

问题:有没有办法将datagrid单元格绑定到对象集合的集合?

我发现这个问题(WPF)看起来很相似,并没有任何帮助。我认为这是同一个问题。 WPF DataGrid: DataGridComboxBox ItemsSource Binding to a Collection of Collections

2 个答案:

答案 0 :(得分:1)

一种可能的解决方案是使用简单的集合作为内部对象,创建一个派生自集合的类,并在其上实现ICustomTypeDescriptor。在接口实现中,迭代集合的元素并相应地填充属性描述符集合。完成后,您应该能够从XAML绑定到这些属性。

示例 - 基于字典的数据对象,您可以将其与其键名绑定(我将所有简单的方法实现压缩为单行):

class DictionaryDataObject : Dictionary<string, object>, ICustomTypeDescriptor
{
    #region ICustomTypeDescriptor Members

    public AttributeCollection GetAttributes() { return AttributeCollection.Empty; }
    public string GetClassName() { return "DictionaryDataObject"; }
    public string GetComponentName() { return null; }
    public TypeConverter GetConverter() { return null; }
    public EventDescriptor GetDefaultEvent() { return null; }
    public PropertyDescriptor GetDefaultProperty() { return null; }
    public object GetEditor(Type editorBaseType) { return null; }
    public EventDescriptorCollection GetEvents(Attribute[] attributes) { return EventDescriptorCollection.Empty; }
    public EventDescriptorCollection GetEvents() { return EventDescriptorCollection.Empty; }
    public PropertyDescriptorCollection GetProperties() { return GetProperties(null); }
    public object GetPropertyOwner(PropertyDescriptor pd) { return this; }

    public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
    {
        var pds =
            this.Keys
            .Select(x => new DictionaryPropertyDescriptor(x))
            .ToArray();
        return new PropertyDescriptorCollection(pds);
    }

    #endregion
}

class DictionaryPropertyDescriptor : PropertyDescriptor
{
    public DictionaryPropertyDescriptor(string name) : base(name, null) { }
    public override bool CanResetValue(object component) { return false; }
    public override Type ComponentType { get { return null; } }
    public override bool IsReadOnly { get { return false; } }
    public override Type PropertyType { get { return typeof(object); } }
    public override void ResetValue(object component) { }
    public override bool ShouldSerializeValue(object component) { return false; }

    public override object GetValue(object component)
    {
        var dic = component as DictionaryDataObject;
        if (dic == null) return null;
        return dic[Name];
    }

    public override void SetValue(object component, object value)
    {
        var dic = component as DictionaryDataObject;
        if (dic == null) return;
        dic[Name] = value;
    }
}

从后面的代码设置示例对象:

DictionaryDataObject ddo = new DictionaryDataObject();

public Window4()
{
    ddo["propa"] = 1;
    ddo["propb"] = "foo";
    ddo["propc"] = "bar";
    ddo["propd"] = 4.5;
    InitializeComponent();
    DataContext = ddo;
}

XAML用法:

<Window.Resources>
    <DataTemplate x:Key="template">
        <WrapPanel>
            <TextBlock Text="{Binding propa}" Margin="5"/>
            <TextBlock Text="{Binding propb}" Margin="5"/>
            <TextBlock Text="{Binding propc}" Margin="5"/>
            <TextBlock Text="{Binding propd}" Margin="5"/>
        </WrapPanel>
    </DataTemplate>
</Window.Resources>
<Grid>
    <ContentControl Content="{Binding}" ContentTemplate="{StaticResource template}"/>
</Grid>

如果要将此解决方案调整为列表而不是字典,则必须根据列表元素的某些属性设置每个属性名称。

答案 1 :(得分:0)

我想我明白你要完成什么,我实际上有一个更优雅的解决方案,它不涉及编写任何自定义类。我写了一篇关于这个问题的博文。该博客面向Silverlight Toolkit中的DataGrid,但您可以轻松修改它以使用任何网格。

The solution is here.

如果您正在寻找,请告诉我。