DataGridComboBoxColumn bound to bool property

Jan 2, 2009 at 11:54 AM
I have a bool property that when false means ascending sort order, and when true means descending sort order.
I would like this to be represented in a DataGrid column as a combo box with the entries "Ascending" and "Descending".

I've read vinsibal's article http://blogs.msdn.com/vinsibal/archive/2008/10/31/wpf-datagrid-datagridcomboboxcolumn-v1-intro.aspx
which states "When the column is bound to a primitive data type such as int, string, or bool, and you want the ComboBox to have a list of similar items to choose from, you can use SelectedItemBinding like so:" so I've tried the following (with the hope that boolean was handled like the integers 0 and 1 and everything would be automagically translated):
                <dg:DataGridComboBoxColumn Header="Order" SelectedValueBinding="{Binding Path=NaturalOrder}">
                    <dg:DataGridComboBoxColumn.ItemsSource>
                        <Collections:ArrayList>
                            <System:String>Ascending</System:String>
                            <System:String>Descending</System:String>
                        </Collections:ArrayList>
                    </dg:DataGridComboBoxColumn.ItemsSource>
                </dg:DataGridComboBoxColumn>

The expected behaviour was that when opening the second column would be set to either Ascending or Descending, and that changing the value using the combo box would affect the true or false setting e source object property.

What happens is that the column is initially shown as empty.  Clicking in a cell brings up the combo drop down, but selecting an item in the drop down has no effect.  The selected value is shown after selecting, but disappears when leaving the cell, and is not preserved when closing and opening the dialog holding the datagrid, which means that the source object hasn't been updated.

Do I need a custom value converter?  If so, where should I put it?  Do I need an ArrayList of something other than String?  I.e. elements that hold both a boolean value and a String presentation?  Or do I need a different collection than ArrayList for the combo content?

Thanx!


- Steinar

 

Jan 2, 2009 at 2:47 PM
Looks like a custom value converter between bool values and the strings used in the combo, may be the way to go.
I'll post back here if (and if not) I get it to work.
Jan 7, 2009 at 12:34 PM

Here's what I did:
 - Wrote a value converter (I put it in the MyPanel.xaml.cs file, of the panel where it would be used, but outside of the class)
 - Added the following at the start of the .xaml file (as the first element inside the top level element)
    <UserControl.Resources>
        <Devices:BoolAndSortTypeNameValueConverter x:Key="BoolConverter" />
    </UserControl.Resources>
 - The Devices namespace is defined as
    xmlns:Devices="clr-namespace:StandardDevices.Devices"
   where what follows "clr-namespace:" is the C# namespace the BoolAndSortTypeNameConverter class resides in
 - Then finally, the binding on the column corresponding to the bool property, is defined as
    <dg:DataGridComboBoxColumn Header="Order" SelectedValueBinding="{Binding Path=NaturalOrder, Converter={StaticResource BoolConverter}}">

The value converter class is defined like this:
namespace StandardDevices.Devices
{
    internal class BoolAndSortTypeNameValueConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return (bool) value ? "Descending" : "Ascending";
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            string stringValue = (string) value;
            if (string.Compare("Ascending", stringValue, StringComparison.Ordinal) == 0)
            {
                return false;
            }

            if (string.Compare("Descending", stringValue, StringComparison.Ordinal) == 0)
            {
                return true;
            }

            return null; // create an exception
        }
    }
}