简体   繁体   English

将自定义数据结构绑定到WPF中的DataGrid ItemsSource

[英]Binding custom data structures to DataGrid ItemsSource in WPF

I'm trying to bind a custom class to the itemssource member of a WPF DataGrid from c#. 我试图从C#将自定义类绑定到WPF DataGrid的itemssource成员。 I implemented IList, but for some reason I can't get the list to show any members. 我实现了IList,但是由于某些原因,我无法显示该列表以显示任何成员。

I'm setting the ItemsSource property in C# by calling 我通过调用在C#中设置ItemsSource属性

    dataGridObject.ItemsSource = switchHolderObject

Here is the definition for my value: 这是我的价值的定义:

    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 {}

The reason I have three classes here is to get around the fact that dictionaries in C# are not covariant. 我这里有三个类的原因是为了避免C#中的字典不是协变的事实。

I have verified that all my implemented IList methods are working properly, and the list does expand and have the appropriate data, but the DataGrid still shows no members. 我已经验证了所有实现的IList方法都可以正常工作,并且列表确实在扩展并且具有适当的数据,但是DataGrid仍然不显示任何成员。 The strange thing is that it works when I add this method to the AssetHolder class: 奇怪的是,当我将此方法添加到AssetHolder类时,它可以工作:

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

and constantly re-bind the DataGrid like this: 并不断像这样重新绑定DataGrid:

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

However, that creates a huge performance hit, and I feel like it should work the way it is. 但是,这会对性能造成巨大影响,我认为它应该按原样工作。 Anyone know what's going on? 有人知道发生了什么吗? Why won't the DataGrid show my data? 为什么DataGrid不显示我的数据?

Edit 编辑

I'v just implemented the IDictionary interface and added a private variable of Dictionary. 我刚刚实现了IDictionary接口,并添加了Dictionary的私有变量。

For demonstration purposes I've only used the Add and GetEnumerator in the Interface. 出于演示目的,我仅在接口中使用了Add和GetEnumerator。 This way we can do this for starters using a testclass Person: 这样,我们可以使用testclass Person为初学者做到这一点:

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: XAML:

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

Just a quick test, but this is the AssetHolder, look at the GetEnumerator(): 只是一个快速测试,但这是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 Class: 人员类别:

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

I figured it out! 我想到了! The reason my implementation didn't work is because I included the INotifyCollectionChanged and INotifyPropertyChanged interfaces, but I was not explicitly telling it when to notify. 我的实现无法正常工作的原因是因为我包含了INotifyCollectionChanged和INotifyPropertyChanged接口,但是我没有明确告诉它何时通知。 When I stopped implementing them, it magically worked! 当我停止实施它们时,它神奇地起作用了!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM