I have a data structure that is an TestDataCollection<TestData> which derives from List<TestData> and implements ITypedList. My TestData object derives from List<T> and has some additional helper properties. Each TestData objects represents a column of data that I want to display in the XamDataGrid. When the TestDataCollection is bound to a xamDataGrid, if I have one item in the collection, the correct data shows, but the column header is wrong (just says Value). But if I have more that one, the correct names show in the Column Headers, but the data is not being displayed.
Our current solution used the ADO.Net DataTable, which binds great for small amounts of data, but I need to scale to 20-30 columns and 10,000,000 rows. I am open to changing this data structure to facilitate fast updatable binding. But I have other objects that also must use this as a bindable source.
Thanks for any help and insight.
public class TestData : List<double> { private string header; private int series = 0; private int sheet = 0; public TestData() : base() { } public string Header { get { return header; } set { header = value; } } public int Series { get { return series; } set { series = value; } } public int Sheet { get { return sheet; } set { sheet = value; } } }
public class TestDataCollection : List<TestData>, ITypedList { private List<string> testDataLUT = new List<string>(); public TestDataCollection() : base() { } public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors) { List<PropertyDescriptor> props = new List<PropertyDescriptor>(); for (int x = 0; x < this.Count; x++) { props.Add(new TestDataPropertyDescriptor(this[x].Header)); } return new PropertyDescriptorCollection(props.ToArray<PropertyDescriptor>(), true); } public void AddTestData(TestData data) { if (testDataLUT.Contains(data.Header)) { int index = testDataLUT.IndexOf(data.Header); this[index].AddRange(data); } else { this.Add(data); } } public TestData GetTestData(string header) { int index = testDataLUT.IndexOf(header); return this[index]; } public string GetListName(PropertyDescriptor[] listAccessors) { return "TestDataCollection"; } }
public class TestDataPropertyDescriptor : PropertyDescriptor { int index = 0; string header = ""; public TestDataPropertyDescriptor(string header) : base(header, null) { this.header = header; } public TestDataPropertyDescriptor(string header, int index) : base(header, null) { this.header = header; this.index = index; } public override bool CanResetValue(object component) { return false; } public override Type ComponentType { get { return typeof(double); } } public override object GetValue(object component) { TestData data = (TestData)component; if (data != null) { for (int x = 0; x < data.Count; x++) { return data[x]; } } else { return 0; } return 0; } public override bool IsReadOnly { get { return true; } } public override Type PropertyType { get { return typeof(double); } } public override void ResetValue(object component) { } public override void SetValue(object component, object value) { } public override bool ShouldSerializeValue(object component) { return false; } }
Thank you Valerie. Using an ITypeList and PropertyDescriptor with a list of Dictionaries solved the problem. I have filed a case with some performance issues, but I believe I am on the right track.
Thanks.
ed
Hello Ed,
Do you have any other questions on this matter?
Sincerely,
Valerie
Developer Support Supervisor - XAML
Infragistics
www.infragistics.com/support
The XamDataGrid expects to be bound to an IEnumerable where the Fields in the grid are the individual properties from the items in the list. The grid is unable to bind each column to a separate collection. If your intent is to display the entries of the List<double> from the first instance of TestData in the first column, this will not work. For example, suppose I create the following data:
collection = new TestDataCollection();
TestData data = new TestData();
data.Header = "My Header";
data.Series = 3;
data.Sheet = 2;
data.Add(0);
data.Add(1);
data.Add(5);
collection.AddTestData(data);
data = new TestData();
data.Header = "My Header2";
data.Sheet = 3;
data.Add(2);
data.Add(9);
data.Add(8);
Although you can indicate to the grid that there should be properties “My Header” and “My Header2” in the object (using ITypedList) to get the appropriate column headers. When the grid calls GetValue for property “My Header” for the first instance of TestData it will only have the list of doubles 0,1,5 and can return 0 for the first cell however when it comes to create the second cell in the row, it won’t know about the second list for “My Header2” since it is still retrieving values for the first row which is bound to the first instance of TestData.
Another option for binding to dynamic data would be to bind to a Collection of dictionaries. Also the following post deals with dynamically creating columns which may be of assistance to you: http://ko.infragistics.com/community/blogs/blagunas/archive/2012/10/24/xamdatagrid-dynamically-create-and-data-bind-columns-with-an-editor-of-your-choice.aspx
Please let me know if you have any questions or if I have misread your current setup.