问题:我试图显示的数据本质上是一些对象集合的集合。因此行可以是任何数字,对于数据网格是正常的,并且列也是任何数字。这对于数据网格来说并不常见。通常,您有一定数量的列,并且您的行会有所不同。 datagrid单元格可以是字符串,也可以通过组合框更改值。
尝试的解决方案:我尝试动态地向数据网格添加列,虽然这很好用(在代码隐藏中添加它们)但我遇到的真正问题是如何绑定到底层对象。数据是动态构建的,我尝试了几种格式。我尝试了一组Arrays,还有ObservableCollection的ObservableCollection。我可以绑定到对象,但由于Silverlight中的Bindings必须绑定到属性,我无法想出以这种方式呈现数据的解决方案。
我的解决方案是以更传统的方式显示数据,包括列表和数据网格。当您在列表中选择一个项目时,它会重新填充数据网格中的数据以显示对象。
问题:有没有办法将datagrid单元格绑定到对象集合的集合?
我发现这个问题(WPF)看起来很相似,并没有任何帮助。我认为这是同一个问题。 WPF DataGrid: DataGridComboxBox ItemsSource Binding to a Collection of Collections
答案 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,但您可以轻松修改它以使用任何网格。
如果您正在寻找,请告诉我。