Using ITypedList to fill DataGrid not working

G

Guest

form code
-----------
ArrayList cList = new ArrayList();
ArrayList aList;

alist= new ArrayList();
aList.Add("Joe");
aList.Add("Smith");
aList.Add("xxx-xxx-xxxx");

cList.Add(alist);

alist= new ArrayList();
aList.Add("Dan");
aList.Add("Tan");
aList.Add("xxx-xxx-xxxx");

cList.Add(alist);



MyGridList cGridList = new MyGridList("Test", cList);
DataGrid.DataSource = cGridList;

Class Code
-----------

public class MyGridList : VirtualList, IList, ITypedList
{
public MyGridList(string pListName, ArrayList pList): base(pListName,
pList)
{

}

public PropertyDescriptorCollection
GetItemProperties(PropertyDescriptor[] listAccessors)
{
ArrayList iPdsList = new ArrayList();
return new
PropertyDescriptorCollection(iPdsList.ToArray(typeof(PropertyDescriptor)) as
PropertyDescriptor[]);
}

}

public class MylList
{

protected string iListName = "";
protected ArrayList iValueList;

public MyList(string pListName, ArrayList pValueList)
{
iListName = pListName;
iValueList = pValueList;
}

public int IndexOf(object value)
{
return 0;
}

public string GetListName(PropertyDescriptor[] listAccessors)
{
return iListName;
}

public object SyncRoot
{
get
{
return null;
}
}

public void Clear()
{
}

public bool Contains(object value)
{
return false;
}

public bool IsFixedSize
{
get
{
return true;
}
}

public void Insert(int index, object value)
{
iValueList.Insert(index, value);
}

public void Remove(object value)
{

}

public int Add(object value)
{
return 0;
}

public bool IsSynchronized
{
get
{
return false;
}
}

public int Count
{
get
{
return this.iValueList.Count;
}
}

public void RemoveAt(int index)
{
iValueList.RemoveAt(index);
}

public object this[int index]
{
get
{
if (index >= this.iValueList.Count) return null;
return this.iValueList[index];
}
set
{
}
}

public IEnumerator GetEnumerator()
{
return this.iValueList.GetEnumerator();
}

public void CopyTo(Array array, int index)
{
}

public bool IsReadOnly
{
get { return true; }
}

}
 
L

Linda Liu [MSFT]

Hi,

Could you please tell me what you'd like the DataGrid to show when you run
the application?

I noticed that you add the following code in the GetItemProperties method:

ArrayList iPdsList = new ArrayList();
return new PropertyDescriptorCollection(iPdsList.ToArray(typeof
PropertyDescriptor)) as PropertyDescriptor[]);

I don't think it would return anything because there's no element in the
ArrayList iPdsList.

If possible, could you please send me a simple sample prooject that could
just reproduce the problem? To get my actual email address, remove 'online'
from my displayed email address.

Sincerely,
Linda Liu
Microsoft Online Community Support

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 
L

Linda Liu [MSFT]

Thank you for your reply and sample project.

In the form1's constructor, you have the following code:

CodeList cList = new CodeList();
KodeDescription code;
code = new KodeDescription("A25.0", "1", "1", "1", "A25.0 Desc");
cList.Add(code);
code = new KodeDescription("B25.0", "2", "2", "2", "B25.0 Desc");
cList.Add(code);

CodeDisplayList cDisplayList = new CodeDisplayList("DX", cList);

dataGridView1.DataSource = cDisplayList;

Do you mean you want to show string array in the first KodeDescription
instance in the first row within the DataGridView and show that of the
second KodeDescription instance in the second row, i.e. show "A25.0" in the
cell (1,1) in the DataGridView, show "1" in the cell(1,2) and "B25.0" in
the cell(2,1)?

Firstly, as I have mentioned in my first reply, the following code in the
GetItemProperties method don't return any PropertyDescriptor:

ArrayList iPdsList = new ArrayList();
// the returned collection has no element
return new
PropertyDescriptorCollection(iPdsList.ToArray(typeof(PropertyDescriptor))
as PropertyDescriptor[]);

Secondly, there's no public properties in the class KodeDescription. What's
more, even though we add a public property for the field atr, this public
property won't appear as a column in the DataGridView.

To get what you want, you need to implement a custom type descriptor for
the class KodeDescription to modify the metadata of this class and get
"virtual" properties, and then call the
TypeDescriptor.GetProperties(typeof(KodeDescription)) in the
GetItemProperties method.
The following is a sample.

public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[]
listAccessors)
{
PropertyDescriptorCollection pdc = null;
pdc= TypeDescriptor.GetProperties(typeof(KodeDescription));

return pdc;
}

In fact, if an ArrayList contains an instance of a custom class and the
ArrayList is bound to a DataGridView, data binding couldn't retrieve the
public properties in the custom class at design time because the elements
in the ArrayList are not of strong type(they're of the type object). So the
DataGridView won't generate columns for the data source at design time. But
when the application is run, data binding will get the public properties of
the elements in the ArrayList through reflection and a column is generated
for each public property at run time.

If you have any question, please feel free to let me know.


Sincerely,
Linda Liu
Microsoft Online Community Support
 
G

Guest

Hi Linda

Thanks for the info - I have 1 more question or clarification

If I add this to class CodeDisplayList

public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[]
listAccessors)
{
PropertyDescriptorCollection pdc = null;
pdc= TypeDescriptor.GetProperties(typeof(KodeDescription));

return pdc;
}

I need to in class KodeDescription expose public data elements

I wanted to expose the cells of an array in a way that it would be flexible -
ie if the array has 5 cells you have 5 columns in the grid, if next time you
have
3 cells you have 3 columns

I can get it to work this way by hardcoding the public elements below - but
is there any mor flexible way to do this ???

Thanks

public class KodeDescription
{
public string[] atr;

public KodeDescription(params string[] patr)
{
atr = patr;
}

public string Code
{
get
{
if (atr.Length>0) return atr[0];
return "";
}
}

public string Description
{
get
{
if (atr.Length > 4) return atr[4];
return "";
}
}

}




Linda Liu said:
Thank you for your reply and sample project.

In the form1's constructor, you have the following code:

CodeList cList = new CodeList();
KodeDescription code;
code = new KodeDescription("A25.0", "1", "1", "1", "A25.0 Desc");
cList.Add(code);
code = new KodeDescription("B25.0", "2", "2", "2", "B25.0 Desc");
cList.Add(code);

CodeDisplayList cDisplayList = new CodeDisplayList("DX", cList);

dataGridView1.DataSource = cDisplayList;

Do you mean you want to show string array in the first KodeDescription
instance in the first row within the DataGridView and show that of the
second KodeDescription instance in the second row, i.e. show "A25.0" in the
cell (1,1) in the DataGridView, show "1" in the cell(1,2) and "B25.0" in
the cell(2,1)?

Firstly, as I have mentioned in my first reply, the following code in the
GetItemProperties method don't return any PropertyDescriptor:

ArrayList iPdsList = new ArrayList();
// the returned collection has no element
return new
PropertyDescriptorCollection(iPdsList.ToArray(typeof(PropertyDescriptor))
as PropertyDescriptor[]);

Secondly, there's no public properties in the class KodeDescription. What's
more, even though we add a public property for the field atr, this public
property won't appear as a column in the DataGridView.

To get what you want, you need to implement a custom type descriptor for
the class KodeDescription to modify the metadata of this class and get
"virtual" properties, and then call the
TypeDescriptor.GetProperties(typeof(KodeDescription)) in the
GetItemProperties method.
The following is a sample.

public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[]
listAccessors)
{
PropertyDescriptorCollection pdc = null;
pdc= TypeDescriptor.GetProperties(typeof(KodeDescription));

return pdc;
}

In fact, if an ArrayList contains an instance of a custom class and the
ArrayList is bound to a DataGridView, data binding couldn't retrieve the
public properties in the custom class at design time because the elements
in the ArrayList are not of strong type(they're of the type object). So the
DataGridView won't generate columns for the data source at design time. But
when the application is run, data binding will get the public properties of
the elements in the ArrayList through reflection and a column is generated
for each public property at run time.

If you have any question, please feel free to let me know.


Sincerely,
Linda Liu
Microsoft Online Community Support
 
L

Linda Liu [MSFT]

Hi,

Thank you for your feedback.
I can get it to work this way by hardcoding the public elements below -
but is there any mor flexible way to do this ???

A more flexible way to do this is to implement a custom type descriptor for
the class KodeDescription to modify the metadata of the class and get
"additional" properties which is not an actually properties in the class.

Note that in your practice, you need to specify the names for the "virtual"
properties in the class KodeDescription. You may add a public field of type
string array for the names of the "virtual" properties in the
KodeDescription class. The following is a sample.

public class KodeDescription
{
// the field properties contains the names for the virtual
properties, e.g. Code, Description and etc.
public string[] properties;
...
public KodeDescription(string[] pprops,params string[] patr)
{
properties = pprops;
atr = patr;
}
}

You may visit my blog article for a sample of how to implement a custom
type descriptor for a class:

http://blogs.msdn.com/msdnts/archive/2007/01/19/how-to-bind-a-datagridview-c
olumn-to-a-second-level-property-of-a-data-source.aspx

If you have any question, please feel free to let me know.

Sincerely,
Linda Liu
Microsoft Online Community Support
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top