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

问题描述

|| 更新 我正在更新这篇文章,因为我做了一些阅读,并决定重新实现我的解决方案。 原始问题:我有一个带有静态属性的类,并且有一个Property是一个动态的属性集合(通过字典)。我想将我的类数据绑定到wpf datagrid,其中每个静态属性应为一列,每个字典条目应为网格中的一列。 经过更多研究后,我决定实现一个propertybag类,其中将包含我的属性和值字典。现在几乎所有东西都在工作。我的网格显示了所有正确的列,并且正确地应用了静态属性值。 但是,现在我无法从字典中获取任何要应用于网格的值,而且我不确定从这里到哪里。 更多信息: 我的数据库有3个表,一个板,一个类别和一个categoryplateassociation表。每个板可具有0到许多类别。现在,我在每个板块中填充所有类别,并将字符串设置为空。然后,当返回关联时(在标牌和类别之间),我在特定类别名称上设置了实数值。这一切都是在创建网格之前发生的。 物业袋:
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); }
    }
}
简单的viewmodel
 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到一列的绑定看起来像这样:
<DataGridTextColumn Header=\"Col4TestKey\" Binding=\"{Binding CustomCategories[test]}\"/>
我真的不知道您的PropertyBag设置器是否可以与绑定一起使用。总而言之,如果您对字典有一套熟悉的键,那么这一切都会奏效。 顺便说一句,我在我的项目中使用平面数据表来处理这种动态内容,确实很容易处理。