Omr*_*ian 8 c# wpf datagrid mvvm
我正在寻找一种方法来显示DataGrid
编译时未知类型的数据.
我有以下基类
public abstract class Entity
{
// Some implementation of methods ...
}
Run Code Online (Sandbox Code Playgroud)
在运行时,我加载一个插件DLL并使用反射来获取从中派生的所有类型的列表Entity
.例如:
public class A : Entity
{
public LocalAddress Address{ get; set; }
}
public class B : Entity
{
public Vendor Vendor { get; set; }
public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
然后我从DB中检索了他们的实例列表
public IEnumerable<Entity> Entities { get; set; } // A list of instances of type A for example
Run Code Online (Sandbox Code Playgroud)
Entities
是DataGrid的ItemsSource
,但是什么是我可以将属性绑定到的最佳方式DataGrid
?由于属性可能很复杂,我还需要能够绑定到特定路径,例如Address.HomeNum
......
我只需要一次显示一个类型实例的一个网格.完整的场景是这样的:
Entity
通过反射从插件DLL 派生的类型列表 A
和B
A
我A
从数据库中获取实例列表- 到目前为止一切顺利.A
的实例中DataGrid
.B
)时,我B
从DB 获取一个实例列表,需要在网格中显示这些实例等等......插件DLL是一个没有xamls的类库(我的用户也是制作这个插件的用户,我不希望他们必须DataTemplate
为他们的实体编写s.我也不能DataTemplate
像我一样制作预测的s我不知道在运行时我需要显示的类型.每种类型都可以有不同类型和数量的属性.我在complie-time中所知道的是它们都来源于Entity
.
一个DataGrid
似乎在这种情况下,不恰当的.如果您的列表绑定到两个单独的实体,它将会严重破坏.
一个更好的选择可能是使用其他一些ItemsControl
并DataTemplate
为每种类型设置一个Entity
.这将允许您为每个实体构建自定义编辑器,并具有要编辑的"列表".
如果您知道实体将始终是单一类型,我会构建该特定类型的集合,并绑定到它.
由于您事先不知道实体的属性名称,因此我认为最好的选择是将 DataGrid 保留在 Xaml 中,但将其 DataGridColumns 的定义和绑定移至后面的代码。
AddColumnsForProperty(PropertyInfo property, string parentPath = "")
{
var title = property.Name;
var path = parentPath + (parentPath=="" ? "" : ".") + property.Name;
if(property.PropertyType == typeof(string))
{
var column = new DataGridTextColumn();
column.Header = title;
column.Binding = new Binding(path);
dataGrid.Columns.Add(column);
}
else if(property.PropertyType == typeof(bool))
{
//use DataGridCheckBoxColumn and so on
}
else
{
//...
}
var properties = property.GetProperties();
foreach(var item in properties)
{
AddColumnsForProperty(item, path);
}
}
Run Code Online (Sandbox Code Playgroud)
现在,如果您执行这些操作,您将填充 dataGrid 列。并通过在可观察集合中添加所需类型的所有实例并将其绑定到 DataGrid 的 ItemsSource ,它应该可以工作。selectedItem 应该是从 Entity 派生的类之一的实例。列表框包含new A()
and new B()
(或 A 和 B 的任何现有实例),因此可以在以下语句中使用 selectedItem。
var propertyList = selectedItem.GetType().GetProperties();
foreach (var property in propertyList)
AddColumnsForProperty(PropertyInfo property);
Run Code Online (Sandbox Code Playgroud)
如何在代码中编写DataGridColumnTemplate
编辑:
在这种情况下不能使用成员,因为 INotifyPropertyChanged 应该参与其中,所以我用属性替换了成员。