2012-03-16 247 views
0

我試圖將自定義類綁定到來自c#的WPF DataGrid的itemssource成員。我實施了IList,但由於某種原因,我無法讓列表顯示任何成員。將自定義數據結構綁定到WPF中的DataGrid ItemsSource

我通過調用

dataGridObject.ItemsSource = switchHolderObject 

這裏設置在C#ItemsSource屬性是我價值的定義:

public class AssetHolder<T> : Dictionary<string,T>, IList<T>, INotifyCollectionChanged, INotifyPropertyChanged where T : Asset 
    { 
     ... // lots of code here 
     new public IEnumerator<T> GetEnumerator() 
     { 
      var enumerator = base.GetEnumerator(); 
      while (enumerator.MoveNext()) 
      { 
       var pair = enumerator.Current; 
       yield return pair.Value; 
      } 
     } 
    } 
    public class NonGenericAssetHolder : AssetHolder<Asset> {} 
    public class SwitchHolder : NonGenericAssetHolder {} 

的原因我這裏有三個類是避開的事實C#中的字典不是協變的。

我已驗證所有實施的IList方法工作正常,並且列表確實展開並具有適當的數據,但DataGrid仍顯示沒有成員。奇怪的是,它的作品,當我加入這個方法的AssetHolder類:

public List<T> Hack() 
    { 
     List<T> result = new List<T>(); 
     foreach (T asset in this) 
     { 
      result.Add(asset); 
     } 
     return result; 
    } 

不斷重新綁定像這樣的DataGrid:

SwitchGrid.ItemsSource = _tempLocation.Switches.Hack(); 

然而,這造成了巨大的性能損失,我覺得它應該像現在這樣。任何人都知道發生了什麼事?爲什麼DataGrid不顯示我的數據?

+0

你實現了GetEnumerator()嗎?你在使用它嗎?注意:我總是將'ItemsControl'的'DataContext'設置爲代碼隱藏,並將Xaml中的ItemsSource設置爲'ItemsSource =「{Binding}」''這樣你就可以更改BindingErrors輸出窗口,因此您可以更好地診斷出現問題。 – Silvermind 2012-03-17 00:49:05

+0

我想,它依賴於地方,你在哪裏填寫AssetHolder類中的數據。你必須把它填入構造函數中,以這種方式使用它。或者,您可以將ItemsSource綁定到Hack方法,但您應該使用AssetHolder 作爲返回類型,IMO:public AssetHolder Hack(){return this; } – JiKra 2012-03-17 01:37:19

+0

@Silvermind Dictionary實現了IEnumerable,所以我只是修改了GetEnumerator函數以僅返回值。我已經確認它可以正常工作,並將其添加到我的帖子中。 – hypehuman 2012-03-17 13:02:27

回答

0

編輯

心中已經只是實現IDictionary接口,並加入字典的私有變量。

出於演示的目的,我只在界面中使用了Add和GetEnumerator。

AssetHolder<Person> persons = new AssetHolder<Person>(); 
persons.Add("One", new Person() { FirstName = "Jack" , LastName = "Jobs" , Age = 63 }); 
persons.Add("Two" , new Person() { FirstName = "Peter" , LastName = "Lastname" , Age = 33 }); 
persons.Add("Three" , new Person() { FirstName = "Wally" , LastName = "Breakfast" , Age = 33 }); 
dataGrid1.DataContext = persons; 

XAML: 這樣我們就可以使用一個TestClass的人首先做到這一點

<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding}" Name="dataGrid1"> 
    <DataGrid.Columns> 
    <DataGridTextColumn Width="1*" Header="FirstName" Binding="{Binding Path=FirstName}"/> 
    </DataGrid.Columns> 
</DataGrid> 

只是一個簡單的測試,但是這是AssetHolder,看的GetEnumerator():

public class AssetHolder<T> : IDictionary<string , T> 
    { 

    Dictionary<string , T> dictionary; 

    public AssetHolder() 
    { 
     dictionary = new Dictionary<string , T>(); 
    } 

    public void Add(string key , T value) 
    { 
     dictionary.Add(key , value); 
    } 

    public bool ContainsKey(string key) 
    { 
     throw new NotImplementedException(); 
    } 

    public ICollection<string> Keys 
    { 
     get { throw new NotImplementedException(); } 
    } 

    public bool Remove(string key) 
    { 
     throw new NotImplementedException(); 
    } 

    public bool TryGetValue(string key , out T value) 
    { 
     throw new NotImplementedException(); 
    } 

    public ICollection<T> Values 
    { 
     get { throw new NotImplementedException(); } 
    } 

    public T this[string key] 
    { 
     get 
     { 
     throw new NotImplementedException(); 
     } 
     set 
     { 
     throw new NotImplementedException(); 
     } 
    } 

    public void Add(KeyValuePair<string , T> item) 
    { 
     throw new NotImplementedException(); 
    } 

    public void Clear() 
    { 
     throw new NotImplementedException(); 
    } 

    public bool Contains(KeyValuePair<string , T> item) 
    { 
     throw new NotImplementedException(); 
    } 

    public void CopyTo(KeyValuePair<string , T>[ ] array , int arrayIndex) 
    { 
     throw new NotImplementedException(); 
    } 

    public int Count 
    { 
     get { throw new NotImplementedException(); } 
    } 

    public bool IsReadOnly 
    { 
     get { throw new NotImplementedException(); } 
    } 

    public bool Remove(KeyValuePair<string , T> item) 
    { 
     throw new NotImplementedException(); 
    } 

    IEnumerator<KeyValuePair<string , T>> IEnumerable<KeyValuePair<string , T>>.GetEnumerator() 
    { 
     throw new NotImplementedException(); 
    } 

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
    { 
     return dictionary.Values.GetEnumerator(); 
    } 
    } 

Person類:

public class Person 
    { 
    public string FirstName { get; set; } 
    public string LastName{get;set;} 
    public int Age { get; set; } 
    } 
+0

我有一些在AssetHolder上調用foreach的c#代碼,但現在它告訴我它無法從KeyValuePair轉換爲AssetObject。我如何指定使用哪個GetEnumerator? – hypehuman 2012-03-17 14:18:18

+0

但是,耶!有用!我不知道爲什麼我的原始解決方案不起作用,但我很高興這一個。 – hypehuman 2012-03-17 14:23:21

+0

@hypehuman很高興工作。你能接受嗎? :) – Silvermind 2012-03-17 14:57:51

0

我想通了!我的實現不起作用的原因是因爲我包含INotifyCollectionChanged和INotifyPropertyChanged接口,但我沒有明確告訴它何時通知。當我停止執行它們時,它神奇地工作了!