Suppose you have a parent-child relationship, and you want to fill a combo with a list of Parent values for a child. For example, you have a Movie object and want to set its Category property. So you make an AllCategories object of type CategoryList and load it with all possible categories, then bind it to your property. Fine.
Until you have a movie that doesn't belong to a particular category, so you want to set the property to null.
An obvious choice would be to add a null to the combo. However, it becomes very ugly and refuses to display the null value. So, you have to construct some non-null object, display it in a custom way, and handle the conversion between this object and null.
Another possible scenario is filtering your movie collection, where choosing the null option would mean "Show all categories".
After some experiments, I've come to this solution. It's definitely not the only possible one, but there are some reasons for using it (see the bottom).
1. Create a DummyObject that implements IEntityObject (as we can only add such objects to an ObjectList) and add a 1-parameter constructor:
public DummyObject (string StringToShow);
The object has to override ToString() to return the string we've provided (StringToShow), since this is a universal way to display this object in a combo;
2. Add it to your collection:
((IList)myCategoryList).Insert(0,new DummyObject("Not set"));
(I'm casting my list of categories to an IList so that I can insert an IEntityObject).
3. After I bind it to a combo, I see the first item is a string "Not set". Here I'm not setting "DisplayMember" nor "ValueMember" parameters of my combo, letting my objects display themselves via the overridden ToString(). I'll be using SelectedItem (rather than SelectedValue), so I'm binding it to the Category property of my Movie object.
Now, what happens if somebody chooses this dummy value? We've bound the SelectedItem to the "Category" property, so it accepts only Categories. If the property isn't nullable, it's perfect -- the combo itself won't allow us to choose this value. If it *is* nullable, we have to convert our dummy to null. We can use a Parse event, for example.
So, in my native language (VB) it looks like this (somebody please translate it to C#!). Assume we have AllCategories collection and cbCategory combo.
Private Sub MyForm_Load(..)
CType(AllCategories, IList).Insert(0, New Support.Dummy("No category selected")) 'add a dummy object
AddHandler Me.cbCategory.DataBindings(0).Parse, AddressOf Combos_Parse 'intercept the Parse event
Private Sub Combos_Parse(ByVal sender As Object, ByVal e As System.Windows.Forms.ConvertEventArgs)
If TypeOf e.Value Is Support.Dummy Then e.Value = Nothing
End Sub
(Dummy.vb)
Public Class Dummy Implements Neo.Core.IEntityObject Private value As String Public ReadOnly Property Context() As Neo.Core.ObjectContext Implements Neo.Core.IEntityObject.Context Get Return Nothing End Get End Property Public ReadOnly Property Row() As System.Data.DataRow Implements Neo.Core.IEntityObject.Row Get Return Nothing End Get End Property Public Overrides Function ToString() As String Return Me.value End Function Public Sub New(ByVal value As String) Me.value = value End Sub End Class
Note that I don't change my model layer at all. Everything happens in the presentation layer. If I choose the "No category selected" string, it's interpreted as Nothing by the combo itself, and this value is passed to the model layer. In other words, my presentation problem (how to display and manage the null option) is solved in the presentation layer.
