user2855206
user2855206

Reputation: 23

WPF DataGrid grouping on a DataGridComboBoxColumn

I have a DataGrid grouping problem which I think is related to the (likely incorrect) manner in which I am binding a list of objects to a DataGridComboBoxColumn. I have searched for solutions here and on Google and have not found anything that works.

  1. I have a Category class:

    public class Category : INotifyPropertyChanged, IEditableObject
    {
    public event PropertyChangedEventHandler PropertyChanged;
    
    // Data for undoing canceled edits.
    private Category temp_Category = null;
    private bool bEditing = false;
    
    private void NotifyPropertyChanged(string name)
      {
      if (PropertyChanged != null)
        {
        PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
      }//NotifyPropertyChanged
    
    private byte _categoryID;
    public byte ID
      {
      get { return _categoryID; }
      set { _categoryID = value; this.NotifyPropertyChanged("ID"); }
      }
    
    private string _categoryText;
    public string CategoryText
      {
      get { return _categoryText; }
      set { _categoryText = value.Trim(); this.NotifyPropertyChanged("CategoryText"); }
      }
    
    // Implement IEditableObject interface.
    public void BeginEdit()
      {
      if (this.bEditing == false)
        {
        this.temp_Category = this.MemberwiseClone() as Category;
        this.bEditing = true;
        }
      }
    
    public void CancelEdit()
      {
      if (this.bEditing == true)
        {
        this.ID = temp_Category.ID;
        this.CategoryText = temp_Category.CategoryText;
        this.bEditing = false;
        }
      }
    
    public void EndEdit()
      {
      if (this.bEditing == true)
        {
        this.temp_Category = null;
        this.bEditing = false;
        }
      }
    }   
    
  2. ...and a List Categories collection used as the ItemSource for the DataGridComboBoxColumn. The list is part of the application's model and is populated on startup.

  3. I have an ObservableCollection (named ItemsIN) of items each of which has a Category property named "Classification".

  4. The ItemsSource for the DataGrid is set in XAML using a DataContext property in the model:

Code behind:

this.Groups = new ListCollectionView(ItemsIN);
this.Groups.GroupDescriptions.Add(new PropertyGroupDescription("Classification.CategoryText"));

XAML:

    <DataGrid AutoGenerateColumns="False" HorizontalAlignment="Stretch" 
        ItemsSource="{Binding Groups}"
    Name="dataGridVariants" VerticalAlignment="Top"  
    VerticalContentAlignment="Center" 
    HorizontalContentAlignment="Stretch" 
    IsSynchronizedWithCurrentItem="{x:Null}"
    CanUserAddRows="False"
    .... etc. etc., styles, column definitions, etc.
    </DataGrid>
  1. Here's the XAML for the DataGridComboBoxColumn:

    <DataGridComboBoxColumn.ElementStyle>
        <Style TargetType="ComboBox">
            <Setter Property="ItemsSource" Value="{Binding Path=DataContext.Categories, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/>
            <Setter Property="IsReadOnly" Value="True"/>
            <Setter Property="Background" Value="LightGreen"/>
            <Setter Property="ItemTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <TextBlock Text="{Binding Path=Category.CategoryText}"/>
                    </DataTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </DataGridComboBoxColumn.ElementStyle>
    
    <DataGridComboBoxColumn.EditingElementStyle>
        <Style TargetType="ComboBox">
            <Setter Property="ItemsSource" Value="{Binding Path=DataContext.Categories, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/>
            <Setter Property="Background" Value="LightGreen"/>                            
            <Setter Property="ItemTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <TextBlock Text="{Binding Path=Category.CategoryText}"/>
                    </DataTemplate>
                </Setter.Value>
            </Setter>                            
        </Style>
    </DataGridComboBoxColumn.EditingElementStyle>
    

  2. The grid loads fine with the DataGridComboBoxColumn items just fine. However, when I change the Category for an item, the grouping fails to reflect the category change. For example, if I have four items shown in category A, and change the category of one item to B, I should get two category groups, one for A and one for B, but I see one group containing three items in category A and one in category B.

If anyone can see my error(s) I would really appreciate it!

Upvotes: 1

Views: 862

Answers (2)

user2855206
user2855206

Reputation: 23

Thanks for your suggestions. I got the grouping to work by changing the ComboBoxColumn ItemsSource binding to this -

`SelectedItemBinding="{Binding Category, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"` 

which is analogous to Winforms DataGridView ComboBoxColumn binding on an object item. I conclude that the UI grouping code depends on detecting a change in the text value associated with at item to be grouped, in this case, the CategoryText. Grouping works fine now; however, when the DataGrid ComboBoxColumn is initialized, it does not show the category associated with the item row. The combobox drop down is populated fine, but the binding must be wrong for the DisplayMemberPath.

Upvotes: 1

Algamest
Algamest

Reputation: 1529

Try this (in code):

this.Groups.DataContext = new ListCollectionView(ItemsIN);

or as itemsIN is an ObservableCollection:

this.Groups.DataContext = itemsIN;

This is because you refer to the DataContext.

<Setter Property="ItemsSource" Value="{Binding Path=DataContext.Categories, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/>

However I don't see anywhere where you explicitly assign to it. This will get your binding fixed I think.

This is an example taken from http://msdn.microsoft.com/en-us/library/system.windows.controls.datagridcomboboxcolumn(v=vs.110).aspx :

<DataGridComboBoxColumn Header="Order Status"  SelectedItemBinding="{Binding Status}" ItemsSource="{Binding Source={StaticResource myEnum}}" />

It may be worth looking at your itemssource. You have an ObservableCollection which is a good choice however I think it may be better have the rest of the binding done in code/ in a collection.

I will look more into this and get back to you here, in the meantime I recommend look at that link if you haven't already. The example at the bottom in particular.

If you do happen to fix this, possibly based on what I've recommended quickly, then good news and I recommend posting your solution. I will look in the meantime as soon as I have a chance.

Upvotes: 0

Related Questions