Search code examples
wpfdatagriddynamicdatagridcomboboxcolumnmultiple-columns

How do I implement a multicolumn ComboBox DataGridColumn in a WPF DataGrid?


I have a simple question that I assume does not have a simple solution. I need to have a multi-column ComboBox for some grid columns in my WPF DataGrid. Is there a known best-practice to accomplish this? From what I have gathered this will require subclassing the DataGridComboBoxColumn to support a custom ComboBox.

I have found some examples of this but not supporting EF entities (I'm using Code First EF).

Any advice is greatly appreciated. Thanks

NOTE: This is all done dynamically with C#. I'm not using XAML to define columns.

Update: What I mean by multicolumn is simply that when you drop the ComboBox down I need to show two values for "Display", even though behind the scenes of course I'm still just storing an ID.

See here:. multicolumn-dropdown http://www.telerik.com/ClientsFiles/188010_multicolumn-dropdown.JPG

With the exception that I need to do this as a DataGridColumn that can be dynamically created and added to a grid, rather than just the simple combo shown in the image.

Update I finally managed to find an article on CodeProject where the author has developed a control with my -exact- requirements. It is located here. Now the only problem I am trying to solve is how to allow the control to work when using Entity Framework (specifically, code first). Getting closer!


Solution

  • I have found the solution for my particular scenario. I downloaded the custom multi-column ComboBox with the included DataGridComboBoxColumn subclass from the link in my last update above. Basically I just made this work with Entity Framework Code-First POCOs and it solved my problem. Here is what I had to do to make it work with POCOs.

    Inside of the CustDataGridComboBoxColumn there are a few overrides. You just need to slightly modify the following two overrides. I’m using reflection to change set the property since I don’t know what it will be from the control.

    The original implementation accomplished this by getting the correct Row from the DataRowView with SelectedValuePath.

    protected override object PrepareCellForEdit(FrameworkElement editingElement, RoutedEventArgs editingEventArgs)
    {
          DataGridCell cell = editingEventArgs.Source as DataGridCell;
          if (cell != null)
          {
            // Changed to support EF POCOs
            PropertyInfo info = editingElement.DataContext.GetType().GetProperty("YourPropertyName", BindingFlags.Public | BindingFlags.Instance);
            object obj = info.GetValue(editingElement.DataContext, null);
            comboBox.SelectedValue = obj;
          }
          return comboBox.SelectedItem;
    }
    
    protected override bool CommitCellEdit(FrameworkElement editingElement)
    {
        // Dynamically set the item on our POCO (the DataContext).
        PropertyInfo info = editingElement.DataContext.GetType().GetProperty(“YourPropertyName”, BindingFlags.Public | BindingFlags.Instance);
        info.SetValue(editingElement.DataContext, comboBox.SelectedValue, null);
        return true;
    }
    

    Also, if you intend on creating this custom control completely in code dynamically instead of in XAML, you will have to add a setter to the Columns property because by default it is set to read-only.

    //The property is default and Content property for CustComboBox
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public ObservableCollection<DataGridTextColumn> Columns
    {
        get
        {
           if (this.columns == null)
           {
               this.columns = new ObservableCollection<DataGridTextColumn>();
           }
           return this.columns;
        }
        set
        {
           this.columns = value;
        }
    }
    

    Thanks for the views and answers provided. Sorry I was unable to adequately word the question to make more sense initially.