C# 使用MVVM在WPF Toolkit DataGrid中显示/编辑复杂对象
我有一个复杂模型的集合,每个模型都包含一个到其他复杂模型的接口实例集合,我需要显示这些父复杂模型和子复杂模型,允许编辑父复杂模型和子复杂模型的所有属性 如何才能最好地显示此数据并允许分别编辑父对象和子对象的属性,以及通过选择多个单元格和上下文菜单单击(即,在多个父对象上更改子模型的相同属性值)的组合进行编辑?我还需要能够执行一些操作,比如通过编辑机制(DataGrid单元当前)中的搜索将模型属性值设置到其他一些复杂模型实例 下面是一个类的通用示例,它近似于我在应用程序中使用的类C# 使用MVVM在WPF Toolkit DataGrid中显示/编辑复杂对象,c#,wpf,mvvm,wpfdatagrid,wpftoolkit,C#,Wpf,Mvvm,Wpfdatagrid,Wpftoolkit,我有一个复杂模型的集合,每个模型都包含一个到其他复杂模型的接口实例集合,我需要显示这些父复杂模型和子复杂模型,允许编辑父复杂模型和子复杂模型的所有属性 如何才能最好地显示此数据并允许分别编辑父对象和子对象的属性,以及通过选择多个单元格和上下文菜单单击(即,在多个父对象上更改子模型的相同属性值)的组合进行编辑?我还需要能够执行一些操作,比如通过编辑机制(DataGrid单元当前)中的搜索将模型属性值设置到其他一些复杂模型实例 下面是一个类的通用示例,它近似于我在应用程序中使用的类 enum Chi
enum ChildType
{
One,
Two,
Three
}
class ComplexType
{
public long ID { get; set; }
public string Name { get; set; }
public override string ToString()
{
return Name;
}
}
class IChildModel
{
ChildType Type { get; set; }
string Name { get; set; }
}
class ChildModel1 : IChildModel
{
public ChildType Type { get; set; }
public string Name { get; set; }
public string Property1 { get; set; }
public decimal Property2 { get; set; }
public ComplexType Property3 { get; set; }
}
class ChildModel2 : IChildModel
{
public ChildType Type { get; set; }
public long Property1 { get; set; }
public string Property2 { get; set; }
}
class Parent
{
public long ID { get; set; }
public string Name { get; set; }
public CustomObservableCollection<IChildModel> Children { get; set; }
}
class ViewModel
{
public CustomObservableCollection<Parent> Parents { get; set; }
}
enum子类型
{
一,,
二,,
三
}
类ComplexType
{
公共长ID{get;set;}
公共字符串名称{get;set;}
公共重写字符串ToString()
{
返回名称;
}
}
类IChildModel
{
子类型类型{get;set;}
字符串名称{get;set;}
}
类ChildModel1:IChildModel
{
公共子类型类型{get;set;}
公共字符串名称{get;set;}
公共字符串属性1{get;set;}
公共十进制属性2{get;set;}
公共ComplexType属性3{get;set;}
}
类ChildModel2:IChildModel
{
公共子类型类型{get;set;}
公共长属性1{get;set;}
公共字符串属性2{get;set;}
}
班级家长
{
公共长ID{get;set;}
公共字符串名称{get;set;}
公共CustomObservableCollection子项{get;set;}
}
类视图模型
{
公共CustomObservableCollection父项{get;set;}
}
到目前为止,我已经使用DataGrid实现了应用程序,并使用反射在视图代码中动态生成了列。子复杂对象实例的列绑定使用CustomObservableCollection上的下标(在本例中,自定义集合允许通过泛型值[enum ChildType]进行索引)。尤其是绑定使得跨多个父对象的子实例在同一属性上正确设置值变得困难(通过对列进行多选和上下文菜单单击来设置值)。同样,我正在处理视图上代码背后的这些大规模更改,使用反射和绑定路径解析来设置属性值(感觉不对;讨厌这样做)。我希望能够在ViewModel上设置选定的子对象,并将属性名称和属性的新值传递给ViewModel中的命令以进行更改。即使能够将命令传递给子类型、属性和新值也不错(我认为)
我通过Google、stackoverflow、Code Project等进行的研究为我指明了当前的解决方案,但我觉得我对这个问题的思考是错误的,应该有更好的MVVM方法来解决这个问题
编辑
此应用程序的主要重点是允许在一个视图中编辑多个父模型实例和子模型实例,在该视图中,用户可以比较多个实例的值,并允许将同一类型的多个对象的父属性或子属性的值设置为相同的值(即Parent1和Parent2都有一个ChildModel1,用户希望将两个父对象的ChildModel1的Property3上的名称设置为“X”)。尽管如此,应用程序仍然必须允许对父对象和子对象上的属性进行单独编辑(DataGrid似乎很好地满足了这一要求).为了满足这些要求,我在视图中实现了动态列创建。下面是此逻辑的一般示例
private void DataGrid_TargetUpdated(object sender, DataTransferEventArgs e)
{
var vm = DataContext as ViewModel;
if (vm != null && vm.Parents != null) {
List<ChildType> processedChildTypes = new List<ChildType>();
foreach (var parent in vm.Parents) {
for (int childIndex = 0; childIndex < parent.Children.Count; ++childIndex) {
var child = vm.Children[childIndex];
if (!processedChildTypes.Contains(child.Type)) { // Ensure each child type is only processed once
processedChildTypes.Add(child.Type);
CreateChildPropertyColumns(processedChildTypes, child);
}
}
}
}
private void CreateChildPropertyColumns(List<ChildType> processedChildTypes, IChildModel child)
{
PropertyInfo[] childProperties = child.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly); // Only use properties declared on the child type
Type childInterfaceType = typeof(IChildModel);
foreach (PropertyInfo childProperty in childProperties) {
// Only create a column if the property is editable
if (childProperty.CanWrite) {
if (childInterfaceType.IsAssignableFrom(childProperty.PropertyType)) {
var subChild = childProperty.GetValue(child, null) as IChildModel;
if (subChild != null && !processedChildTypes.Contains(subChild.Type)) {
processedChildTypes.Add(subChild.Type);
CreateChildPropertyColumns(processedChildTypes, subChild);
}
}
else
dataGrid.Columns.Add(CreateChildPropertyColumn(child.Type, childProperty));
}
}
}
private DataGridColumn CreateChildPropertyColumn(ChildType childType, PropertyInfo propertyInfo)
{
DataGridColumn column = null;
var binding = new Binding(string.Format("Children[{0}].{1}", childType, propertyInfo.Name));
/* Create column based on PropertyInfo here */
/* Default case is a text column */
column = new DataGridTextColumn() { Binding = binding };
column.Header = propertyInfo.Name;
return column;
}
private void DataGrid\u TargetUpdated(对象发送方、数据传输方)
{
var vm=DataContext作为ViewModel;
if(vm!=null&&vm.Parents!=null){
List processedChildTypes=new List();
foreach(vm.Parents中的var parent){
对于(int childIndex=0;childIndex