Go Back

Silverlight RadGrid with Templated Combobox Cells

Telerik’s ComboboxColumn for the Silverlight RadGrid is highly useful for presenting drop-down list options for the user in a grid-editing scenario.  But it’s also very easy to template, and you can even template the ‘Display’ look of the cells to match that of your dropdown list items.  Using templates, we have the ability to display the dropdown choices using data-driven visual elements, for a much richer user experience.

Here’s an example of using a simple template that utilizes a custom Background and Foreground color, based upon properties of the underlying data.  First, a look at the sample data used for demonstration.

This example uses 2 sample classes.  One represents a list item that contains color information, and one is a data item with a property to hold the ID for a MyColorItem value.  Although I am demonstrating with foreground and background colors, any sort of visual setting could be used and incorporated into your template: an image path, a font, etc.  Notice we are using a nullable ID, so the users can actually choose an empty choice to clear the cell.  This is not necessary, but is sometimes nice to have.

public class MyColorItem
    {
        public int? ID { get; set; }
        public string ColorItemName { get; set; }
        public string FGColor { get; set; }
        public string BGColor { get; set; }
    }
    public class MyGridItem
    {
        public int? MCItemID { get; set; }
        public string Name { get; set; }
    }

Now the main test page code, just a set of sample data and a sample list to serve as the itemssource for the dropdown in the combobox editor.

public partial class MainPage : UserControl
{
    public List<MyGridItem> myTestItems = new List<MyGridItem>(){
            new MyGridItem(){ Name = "my test 1", MCItemID = 2},
            new MyGridItem(){ Name = "my test 2", MCItemID = 1},
            new MyGridItem(){ Name = "my test 3", MCItemID = 0},
            new MyGridItem(){ Name = "my test 4", MCItemID = null},
            new MyGridItem(){ Name = "my test 4", MCItemID = 3} };

    public List<MyColorItem> sourceList = new List<MyColorItem>(){
        new MyColorItem(){ ID = null, ColorItemName= "null", FGColor="000000", BGColor="FFFFFF"},
        new MyColorItem(){ ID = 0, ColorItemName= "List Item 0", FGColor="FFFF00", BGColor="000033"},
        new MyColorItem(){ ID = 1, ColorItemName= "List Item 1", FGColor="330066", BGColor="FF0099"},
        new MyColorItem(){ ID = 2, ColorItemName= "List Item 2", FGColor="CC00CC", BGColor="000000" },
        new MyColorItem(){ ID = 3, ColorItemName= "List Item 3", FGColor="00FF00", BGColor="660066"} };

Here’s where I am setting up the columns for the RadGrid, just one regular column and one of our CustomComboBoxColumns, which is going to allow us to apply the same template we use for our grid cells to the dropdown list items.

public MainPage()
{
    InitializeComponent();
    mainGrid.IsFilteringAllowed = true;
    //adding the dummy columns
    GridViewDataColumn col1 = new GridViewDataColumn() { UniqueName = "Name" };
    mainGrid.Columns.Add(col1);
    GridViewComboBoxColumn comboBoxColumn = new CustomComboBoxColumn();
    comboBoxColumn.UniqueName = "MCItemID";
    comboBoxColumn.DataMemberBinding = new Binding()
    {
        Mode = BindingMode.TwoWay,
        Path = new PropertyPath("MCItemID"),
        Converter = new comboboxConveter(),
        ConverterParameter = sourceList
    };
    comboBoxColumn.ItemsSource = sourceList;
    comboBoxColumn.CellStyle = Application.Current.Resources["CustomColorCellStyle"] as Style;
    mainGrid.Columns.Add(comboBoxColumn);
    mainGrid.ItemsSource = myTestItems;
}

We need a converter on the DataBinding of the column, this lets us use an actual ‘MyColorItem’ object as the data in the cell, so that we can access properties of that object in the DataTemplate we apply. This is different than when we just want the ComboboxColumn to use a DisplayMemberPath and a SelectedValueMemberPath to do the conversion for us (say, if we we doing an ID-to-text conversion only).  In this case, we actually want the MyColorItem object to be returned from the converter.

public class comboboxConveter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        List<MyColorItem> sourcelist = parameter as List<MyColorItem>;
        if (sourcelist != null && value != null)
            return sourcelist.First(p => p.ID == (int)value);
        return null;
    }
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        int i;
        if (value != null && Int32.TryParse(value.ToString(), out i))
            return i;
        return null;
    }
}

Our custom combobox column just overrides the CreateCellEditElement method, which gives us a bit more control over the editor.  In this case, we want to apply our own styles to the SelectionBoxItemTemplate and the ItemContainerStyle, so we copy the binding from the auto-generated combobox and instead return our own custom version.

public class CustomComboBoxColumn : GridViewComboBoxColumn
{
    public override FrameworkElement CreateCellEditElement(GridViewCell cell, object dataItem)
    {
        FrameworkElement editor = base.CreateCellEditElement(cell, dataItem);
        Binding gb = editor.GetBindingExpression(RadComboBox.SelectedValueProperty).ParentBinding;
        RadComboBox cb = new RadComboBox() { ItemsSource = ItemsSource, SelectedValuePath = "ID" };
        cb.ItemContainerStyle = Application.Current.Resources["CustomColorComboBoxItemStyle"] as Style;
        cb.SelectionBoxItemTemplate = Application.Current.Resources["ColorItem_DT"] as DataTemplate;
        Binding binding = new Binding() { Path = gb.Path, Mode = gb.Mode };
        cb.SetBinding(RadComboBox.SelectedValueProperty, binding);
        return cb;
    }
}

And lastly, we need a converter to convert those color strings into brushes for our template.

public class StringtoColorConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value != null)
            return GetColorFromHexString(value.ToString());
        return new SolidColorBrush(Colors.Transparent);
    }
    public static SolidColorBrush GetColorFromHexString(string hexaColor)
    {
        return new SolidColorBrush( Color.FromArgb( 255, System.Convert.ToByte(hexaColor.Substring(0, 2), 16), 
            System.Convert.ToByte(hexaColor.Substring(2, 2), 16), System.Convert.ToByte(hexaColor.Substring(4, 2), 16)));
    }

Now, the XAML!  This is the really great part, where one template can be used in both the cell and the dropdown list items.  Here’s our very simple template, using the FGColor and BGColor properties, along with our converter to get the brush colors.

image

And the template and style for our cells.  Here, we use our custom template for display, but in the Editing state, we return the template to it’s regular value, which allows it to switch over to the Combobox when the cell goes into edit mode.

image

And for the combobox item template (how the items look in the dropdown), we again use our custom DataTemplate for the content.

image

Whew!  Ok, with all the pieces in place, our grid will use our custom template in 3 places: for display, as the selected item in the editor, and for the dropdown items in the editor!  Notice with this setup, we get sorting and filtering also enabled, so we don’t lose any column functionality with our custom column and cells.

image image

Not that this is the only way to get to this same result, but it is a nice way to re-use templates, no matter how complicated they get, and to ensure that each time the template is applied to the proper datatype to work correctly.  For more information on Telerik’s RadGrid for Silverlight, look at the detailed documentation here, or check out Falafel’s own training and consulting services.

  • Facebook
  • Twitter
  • DZone It!
  • Digg It!
  • StumbleUpon
  • Technorati
  • Del.icio.us
  • NewsVine
  • Reddit
  • Blinklist
  • Add diigo bookmark
Post a comment!
  1. Formatting options