2011-05-24 77 views
2

修訂WPF Datagrid的數據綁定與靜態屬性和字典包含類的動態屬性值項

,因爲我做了一些更多的閱讀,並決定重新實現我的解決方案我更新這個帖子。

原問題:我有一個具有靜態屬性的類和一個屬性(通過字典)的動態集合的屬性。我想將我的類綁定到一個wpf數據網格,其中每個靜態屬性應該是一個列,每個字典條目應該是網格中的一列。

在做了一些更多的研究之後,我決定實現一個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); } 
    } 
} 

簡單視圖模型

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); 
    } 
} 
+0

你是否將一個板對象或板對象的集合綁定到數據網格?數據網格應該如何顯示,應該顯示什麼?順便說一句,我真的不知道你爲什麼使用PropertyDescriptor。 – blindmeis 2011-05-24 05:39:50

+0

我將ObservableCollection 綁定到數據網格。我使用PropertyDescriptor作爲操縱網格中顯示的屬性的一種方法。這是我無法工作的部分。我想將字典中的每個條目設置爲板的屬性,其中名稱是屬性名稱,值是屬性值。我會用這個方向走錯方向嗎? – emelious 2011-05-24 13:16:51

回答

0

做你的字典在您的屬性包有一個固定的大小或不鍵被稱爲?

你不發表您的XAML爲你的數據網格,但是從PropertyBag中一列的結合看起來是這樣的:

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

我真的不知道你閹二傳手的PropertyBag將結合工作。總而言之,只要你有一套知道你的字典的密鑰就行。

順便說一句,我在我的項目中使用平坦的datatables這種動態的東西,真的很容易處理。

+0

直到從數據庫加載它們的運行時間,我纔會知道類別名稱集(我的字典的鍵)。用戶可以添加和刪除數據庫中的類別,因此我無法對類別名稱進行硬編碼。但是,你是對的,如果我事先知道這些名字,這將是一個簡單的問題來解決。 – emelious 2011-05-24 17:05:26