Introduction
An often recurring task is to visualize collections of objects. This article explains how to use an adapter class to fill a ListView
control with completely arbitrary objects.
Using the ListViewAdapter
The ListViewAdapter
must get some basic information about which properties it should display:
adapter.AddBinding("Name","The name",100);
adapter.AddBinding("Comment","Comments?",100);
adapter.Fill(myListView,myCollection);
This is enough to get the adapter to display your objects. You could throw an object at it that doesn't have any of the properties Name
and Comment
. It would work, but a blank row will just look silly, so please don't.
The myCollection
object must implement the interface IEnumerable
. Most collections do, so this shouldn't be a problem.
How it works
What makes this piece of magic work is - as most of you probably have figured out - reflection. Reflection is used to discover type information runtime to handle objects that are unknown when you wrote the code.
The first step when the adapter fills a ListView
with objects is to remove existing columns and ListViewItem
s. Secondly, it iterates through the bindings and creates the columns. Then it starts filling the ListView
with items:
Type t=obj.GetType();
ListViewItem item=new ListViewItem();
bool first=true;
foreach(ColumnBinding b in bindings)
{
PropertyInfo p=t.GetProperty(b.Property);
string text=string.Empty;
if(p!=null)
{
object val=p.GetValue(obj,null);
if(val!=null)
{
text=b.Parser.Parse(val);
}
}
if(first)
item.Text=text;
else
item.SubItems.Add(text);
first=false;
}
This is the part of the code that builds the actual ListViewItem
. It is pretty straightforward. It loops through the column bindings and tries to get the value, as an object
, of the property that is bound to the column. Then it sends the object
to the parser, which I will explain later, and adds the string returned from the parser to the ListViewItem
.
There is some additional code which handles images. But if you get the principles of this part of the code, you'll understand how it works when you look at it.
The Parser
The Parser arose from the need to display information that was interpreted in some way. It is not always desirable to display the result of a .ToString()
call. A Parser object doesn't do anything else than return the result of .ToString()
. But it can be extended to allow more creative interpretations.
An example of a class that extends Parser is the CustomParser
class. The custom parser overrides the Parse
method of its base class and replaces it with a method that uses a delegate to parse the object. So if you don't feel like writing a new class just to parse an object, you can just use the custom parser and provide it with a suitable delegate to do the job.
I'm 23 years old and I study informatics at the university of Lund. I'm currently working on my bachelor thesis on predicate logic in .Net.
When it comes to development I'm totally hooked on .Net, it is probably the most exiting platform to work on today, and I'm looking forward to its second incarnation in Longhorn.