2012-03-16 2 views
0

Я пытаюсь связать пользовательский класс с элементом itemssource WPF DataGrid из C#. Я реализовал IList, но по какой-то причине я не могу получить список, чтобы показывать всех участников.Связывание пользовательских структур данных с DataGrid ItemsSource в WPF

Я устанавливаю свойство ItemsSource в C# по телефону

dataGridObject.ItemsSource = switchHolderObject 

Вот определение для моего значения:

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()' правильно? Вы используете его? На стороне примечание: я всегда устанавливаю 'DataContext'' ItemsControl' в кодировке и устанавливаю 'ItemsSource' в Xaml только для' ItemsSource = "{Binding}" 'таким образом, у вас больше изменений BindingErrors, появляющихся в в окне вывода, чтобы вы могли лучше диагностировать, что происходит. – Silvermind

+0

Я думаю, он зависит от места, где вы заполняете данные в классе AssetHolder. Вы должны заполнить его в конструкторе, чтобы использовать его так, как это. Или вы можете связать ItemSource с методом Hack, но вы должны использовать AssetHolder как тип возврата, IMO: public AssetHolder Hack() {return this; } – JiKra

+0

@Silvermind Dictionary реализует IEnumerable, поэтому я только что изменил функцию GetEnumerator, чтобы вернуть только значения.Я подтвердил, что он работает правильно, и я добавил его в свой пост выше. – hypehuman

ответ

0

Редактировать

I'v только реализован интерфейс IDictionary и добавил приватную переменную из словаря.

Для демонстрационных целей я использовал только Add и GetEnumerator в интерфейсе. Таким образом, мы можем сделать это для начала, используя TestClass лицо:

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:

<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(); 
    } 
    } 

лицо Класс:

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

У меня есть код C#, который вызывает foreach в AssetHolder, но теперь он говорит мне, что он не может преобразовать из KeyValuePair в AssetObject. Как указать, какой GetEnumerator использовать? – hypehuman

+0

Но yay! Оно работает! Я не уверен, почему мое оригинальное решение не сработало, но я рад, что это делает. – hypehuman

+0

@hypehuman Рад, что это сработало. Не могли бы вы согласиться? :) – Silvermind

0

Я понял! Причина, по которой моя реализация не работала, заключается в том, что я включил интерфейсы INotifyCollectionChanged и INotifyPropertyChanged, но я не говорил об этом, когда уведомлял. Когда я прекратил их реализовывать, он волшебным образом работал!

Смежные вопросы