Search code examples
c#wpfdatagriddatagridtemplatecolumndatagridcomboboxcolumn

Why does a DataGridComboBoxColumn yield no results wheras a DataGridTemplateColumn with a ComboBox does?


If I AutoGenerate Columns in a DataGrid, Array and Collection Items do not automaticaly become DataGridComboBoxColumn, or they don't appear to be...

This code:

   <DataGrid x:Name="dataGrid" Grid.Row="1" ItemsSource="{Binding SrcCollection}" AutoGenerateColumns="False" SelectionMode="Single" 
   AlternatingRowBackground="{DynamicResource {x:Static SystemColors.GradientActiveCaptionBrushKey}}" AlternationCount="1"
   IsReadOnly="True" >
         <DataGrid.RowStyle>
            <Style>
               <Setter Property="DataGridRow.IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
            </Style>
         </DataGrid.RowStyle>
         <DataGrid.Columns>
            ...
            <DataGridComboBoxColumn ItemsSource="{Binding Path=MetadataMap}" Header="MetadataMap"  IsReadOnly="True" />
            <DataGridTemplateColumn Header="MetadataMap" IsReadOnly="True">
               <DataGridTemplateColumn.CellTemplate>
                  <DataTemplate>
                     <ComboBox ItemsSource="{Binding Path=MetadataMap}" SelectedIndex="0"  />
                  </DataTemplate>
               </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            ...
            <DataGridComboBoxColumn ItemsSource="{Binding Path=Rights}" Header="Rights" IsReadOnly="True" />
            <DataGridTemplateColumn Header="Rights" IsReadOnly="True">
               <DataGridTemplateColumn.CellTemplate>
                  <DataTemplate>
                     <ComboBox ItemsSource="{Binding Path=Rights}" SelectedIndex="0" />
                  </DataTemplate>
               </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            ...
         </DataGrid.Columns>
      </DataGrid >

produces the following results:

enter image description here

So how can I get the to work properly, ideally with Auto Generation, so I don't need to generate hundreds of DataGrid definitions?


Solution

  • In search for an answer, I stumbled upon this post, and this one. Although they are more about manipulating the content, I was able to modify it, and get it to do what I need.

    Here is the Class I created:

      public class MyDataGridComboBoxColumn : DataGridComboBoxColumn
      {
        public string ColumnName
        {
          get;
          set;
        }
    
        protected override System.Windows.FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
        {
          var element = (dynamic)base.GenerateElement(cell, dataItem);
          ComboBox CB = new ComboBox();
          try
          {
            dynamic Value = dataItem.GetType().GetProperty(cell.Column.Header.ToString()).GetValue(dataItem, null);
            CB = new ComboBox();
            if (Value != null)
              foreach (var val in Value)
                CB.Items.Add(val);
            CB.SelectedIndex = 0;
          }
          catch { }
          return CB;
        }
      }
    

    Then I over rode the DataGrid's AutoGenerating Event:

    private void AutoGenerating(object sender, DataGridAutoGeneratingColumnEventArgs e)
    {
      if (e.PropertyType.IsArray || 
        e.PropertyType.ToString().ToUpperInvariant().Contains("Dictionary".ToUpperInvariant()) ||
        e.PropertyType.ToString().ToUpperInvariant().Contains("List".ToUpperInvariant()))
      {
        MyDataGridComboBoxColumn col = new MyDataGridComboBoxColumn();
        col.ColumnName = e.PropertyName;
        e.Column = col;
        e.Column.Header = e.PropertyName;
      }
    }
    

    I'm sure, that this is not the best method, and would appreciate any helpfull suggestions.