c# - WPF Datagrid 数据绑定(bind)到具有静态属性的类和包含动态属性值条目的字典

标签 c# wpf datagrid propertydescriptor icustomtypedescriptor

更新

我正在更新这篇文章,因为我做了更多阅读并决定重新实现我的解决方案。

原始问题:我有一个具有静态属性的类和一个属性,该属性是属性的动态集合(通过字典)。我想将我的类数据绑定(bind)到 wpf 数据网格,其中每个静态属性应该是一列,每个字典条目应该是网格中的一列。

在做了更多研究之后,我决定实现一个 PropertyBag 类,它将包含我的属性和值字典。现在几乎一切正常。我的网格显示了所有正确的列,并且正确应用了静态属性值。

但是,现在我无法从字典中获取任何要应用于网格的值,而且我不确定从这里该去哪里。

更多信息:

我的数据库有3张表,一个plate,一个category,还有一个categoryplate关联表。每个板 block 可以有 0 到多个类别。现在,我用所有类别填充每个盘子并将字符串设置为空。然后,当返回关联时(在板 block 和类别之间),我在特定类别名称上设置实际值。这一切都发生在网格创建之前。

属性(property)袋:

public class PropertyBag
{
    private readonly Dictionary<string, string> values = new Dictionary<string, string>();

    public string this[string key]
    {
        get 
        {
            string value;
            values.TryGetValue(key, out value);
            return value;
        }
        set
        {
            if (value == null) values.Remove(key);
            else values[key] = value;
        }
    }
}

修订版类

[TypeDescriptionProvider(typeof(PlateTypeDescriptionProvider))]
public class Plate : INotifyPropertyChanged
{
    public int ID;
    private string name;
    private string status;
    private string creator;
    private Uri location;
    private string description;

    public Plate()
    {
        CustomCategories = new PropertyBag();
    }

    public PropertyBag CustomCategories { get; set; }

    public string Name
    {
        get { return name;}
        set
        {
            name = value;
            NotifyPropertyChanged("Name");
        }
    }

    public string Status
    {
        get { return status; }
        set
        {
            status = value;
            NotifyPropertyChanged("Status");
        }
    }

    public string Creator
    {
        get { return creator; }
        set
        {
            creator = value;
            NotifyPropertyChanged("Creator");
        }
    }

    public Uri Location
    {
        get { return location; }
        set
        {
            location = value;
            NotifyPropertyChanged("Location");
        }
    }

    public string Description
    {
        get { return description; }
        set
        {
            description = value;
            NotifyPropertyChanged("Description");
        }
    }

    public static Plate ConvertDataPlateToBusinessPlate(TestPlate dataPlate)
    {
        var plate = new Plate
                        {
                            Name = dataPlate.Name, 
                            Status = dataPlate.Status,
                            Creator = dataPlate.Creator, 
                            Description = dataPlate.Description, 
                            Location = new Uri(dataPlate.Location)
                        };
        return plate;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

修改后的 CustomTypeDescriptor:

public override PropertyDescriptorCollection GetProperties()
    {
        return GetProperties(null);
    }

    public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
    {
        var properties = new ArrayList();
        foreach (PropertyDescriptor propertyDescriptor in base.GetProperties(attributes))
        {
            if(propertyDescriptor.PropertyType.Equals(typeof(PropertyBag)))
            {
                //Static list of all category names
                var categoryNames = Categories.GetAll();
                foreach (var categoryName in categoryNames)
                {
                    properties.Add(new PropertyBagPropertyDescriptor(categoryName));
                }
            }
            else
            {
                properties.Add(propertyDescriptor);
            }

        }
        var props = (PropertyDescriptor[])properties.ToArray(typeof(PropertyDescriptor));
        return new PropertyDescriptorCollection(props);
    }

修改后的 PropertyDescriptor

    public class PropertyBagPropertyDescriptor : PropertyDescriptor
{
    public PropertyBagPropertyDescriptor(string name) : base(name, null)
    {}

    public override bool CanResetValue(object component)
    {
        return true;
    }

    public override object GetValue(object component)
    {
        return ((PropertyBag) component)[Name];
    }

    public override void ResetValue(object component)
    {
        ((PropertyBag)component)[Name] = null;
    }

    public override void SetValue(object component, object value)
    {
        ((PropertyBag) component)[Name] = (string) value;
    }

    public override bool ShouldSerializeValue(object component)
    {
        return ((PropertyBag)component)[Name] != null;
    }

    public override Type ComponentType
    {
        get { return typeof(PropertyBag); }
    }

    public override bool IsReadOnly
    {
        get { return false; }
    }

    public override Type PropertyType
    {
        get { return typeof(string); }
    }
}

简单的 View 模型

 public TestPlateAdministratorViewModel()
    {
        CommandAggregator = new TestPlateAdministratorCommandAggregator(this);
        LoadData();
    }

    public static TestPlateAdministratorCommandAggregator CommandAggregator { get; set; }
    public ObservableCollection<Plate> TestPlates{ get; set; }

    private static void LoadData()
    {
        CommandAggregator.LoadPlatesCommand.Execute(null);
        CommandAggregator.LoadCategoriesCommand.Execute(null);
    }
}

最佳答案

PropertyBag 中的 Dictionary 是否具有固定大小或键是否已知?

您没有为您的数据网格发布您的 xaml,但是从 propertybag 到一列的绑定(bind)可能如下所示:

<DataGridTextColumn Header="Col4TestKey" Binding="{Binding CustomCategories[test]}"/>

我真的不知道您的 PropertyBag setter 是否适用于绑定(bind)。总而言之,如果您有一组已知的字典键,这一切都会起作用。

顺便说一句,我在我的项目中使用平面数据表来处理这些动态的东西,它们真的很容易处理。

关于c# - WPF Datagrid 数据绑定(bind)到具有静态属性的类和包含动态属性值条目的字典,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6104541/

相关文章:

c# - C# 相当于 Java 的 Enumeration<>

c# - 如何解决 Visual Studio : "Parameter ?_1 has no default value."? 中的此错误

c# - DataGrid 中的 WPF 绑定(bind)到 DataContext

apache-flex - Flex 垂直数据网格

wpf - Grid 的 SharedSizeGroup 和 * 大小调整

javascript - 从网格 ExtJs 4 中获取一行

c# - 如何在 StyleCop 中执行私有(private)方法的文档?

c# - 在 VS 调试器中获取方法的返回值

c# - 访问基本成员时未调用子静态构造函数

WPF ListView 项目单击的名称