Introduction
While the version of Depends4Net I presented in the previous part of this series works well enough when you have .NET 4.0 installed on the target system, there are times when .NET 4.0 is not available – so here is the .NET 2.0 version of the utility.
Be aware that it will not be happy about .NET 4.0 assemblies, but it has no problems with .NET 3.0 and 3.5 …
While Windows Forms programming has been dealt with in several very good articles here on CodeProject – there is one piece generally missing from the puzzle: An easy to use component for binding to a collection of custom data types.
Creating a Custom datasource for Windows Forms databinding
As usual, when you want to create something in .NET, it pays off to examine what’s already there, and as I like to do my Windows Forms development using the visual designer, I must present the framework with something it knows how to handle.
In this case, assemblyDataList
is an instance of AssemblyDataList
and assemblyBindingSource
is an instance of our well known friend System.Windows.Forms.BindingSource
. I want to be able to configure the BindingSource
using the visual design in the usual way:
And it should also be fairly easy to implement new components that expose collections of custom types to Windows Forms databinding. The complete source code for AssemblyDataList
looks like this:
public class AssemblyDataList : BindingComponent<AssemblyData>
{
}
That doesn’t look too hard, so I’m pretty happy about the generic BindingComponent<T>
class.
The generic BindingComponent<T>
obviously needs to be derived from System.ComponentModel.Component
to be supported by the designer, and it needs to implement the ITypedList
interface to provide BindingSource
with the information it needs to facilitate databinding. .NET also provides a generic BindingList<T>
class that suits my purpose.
public class BindingComponent<T> : Component, IBindingList, ITypedList
{
BindingList<T> items;
public event ListChangedEventHandler ListChanged;
public BindingComponent()
{
items = new BindingList<T>();
items.ListChanged += items_ListChanged;
}
void items_ListChanged(object sender, ListChangedEventArgs e)
{
if (ListChanged != null)
{
ListChanged(this, e);
}
}
protected override void Dispose(bool disposing)
{
items.ListChanged -= items_ListChanged;
base.Dispose(disposing);
}
[ListBindable(true)]
[Bindable(true)]
[Browsable(true)]
public BindingList<T> Items
{
get
{
return items;
}
}
As IBindingList
requires me to implement the “event ListChangedEventHandler ListChanged;
”, I just implement it by wrapping the event on the BindingList<T>
, and implement the rest of the IBindingList
interface by wrapping the functionality of the BindingList<T>
class. So basically BindingComponent<T>
is a component that wraps BindingList<T>
.
ITypedList
requires me to implement two methods; GetItemProperties
that returns a PropertyDescriptorCollection
and GetListName
that returns the name of the list as a string
, and it turns out that .NET provides a ready to use reusable implantation in the form of the System.Windows.Forms.ListBindingHelper
class.
private PropertyDescriptorCollection propertyDescriptorCollection;
public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors)
{
if (listAccessors != null && listAccessors.Length > 0)
{
PropertyDescriptorCollection result =
ListBindingHelper.GetListItemProperties(items, listAccessors);
return result;
}
else
{
if (propertyDescriptorCollection == null)
{
propertyDescriptorCollection =
TypeDescriptor.GetProperties(typeof(T), new Attribute[]
{ new BrowsableAttribute(true) });
}
return propertyDescriptorCollection;
}
}
public string GetListName(PropertyDescriptor[] listAccessors)
{
if (listAccessors != null && listAccessors.Length > 0)
{
return ListBindingHelper.GetListName(items, listAccessors);
}
else
{
return typeof(T).Name;
}
}
So .NET provides me with all I need to easily implement the generic BindingComponent<T>
class.
Concluding Remarks
Creating custom components that facilitate binding to collections of data is, as you can see, really easy to implement. I usually expose data from the business model of my applications using similar techniques – and this makes it easy for other developers to rapidly create user interfaces where little or sometimes no coding is required.
Just drag the component from the Toolbox onto the form, and use the tools provided with Visual Studio to rapidly create fairly complex Windows Forms based user interfaces.
What’s Next
Originally I wanted to use the WPF DataGrid
, but “ExpressionDark.xaml” does not contain a style for the DataGrid
. A preview of an “ExpressionDark
” style for the DataGrid
is now included with the “Harlinn.Depends4Net
” project included with the download.
The next article will tackle styling of the DataGrid
– and I expect the result will improve the look of the application.
History
- 30th August, 2011 - Initial posting