I'm trying to bind a custom class to the itemssource member of a WPF DataGrid from c#. I implemented IList, but for some reason I can't get the list to show any members.
I'm setting the ItemsSource property in C# by calling
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.
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. The strange thing is that it works when I add this method to the AssetHolder class:
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:
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?
Edit
I'v just implemented the IDictionary interface and added a private variable of Dictionary.
For demonstration purposes I've only used the Add and GetEnumerator in the Interface. This way we can do this for starters using a 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:
<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():
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; }
}