Search code examples
c#wpfxaml

DataGridComboBoxColumn selection is applied to all ComboBoxes in Column


When I make a selection in a ComboBox within a DataGridComboBoxColumn, the selection is applied to all the ComboBoxes. This only happens if I set the ElementStyle of the DataGridComboBox.

Does anyone know why I am seeing this behaviour?

I have attached all the code needed to recreate this issue below.

ViewModel

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace WpfDotNetFramework472
{
    public class CompareSelectionViewModel
    {
        public CompareSelectionViewModel()
        {
            Items.Add(new ItemViewModel { ItemNumber = 1, ItemType = ItemType.None });
            Items.Add(new ItemViewModel { ItemNumber = 2, ItemType = ItemType.NewItem });
            Items.Add(new ItemViewModel { ItemNumber = 3, ItemType = ItemType.OldItem });
            Items.Add(new ItemViewModel { ItemNumber = 4, ItemType = ItemType.BrokenItem });
        }

        public ObservableCollection<ItemViewModel> Items { get; } = new ObservableCollection<ItemViewModel>();

        public IEnumerable<ItemType> AllowedItems { get; } = new ObservableCollection<ItemType>
        {
            ItemType.None,
            ItemType.BrokenItem,
            ItemType.NewItem,
            ItemType.OldItem
        };
    }
    public class ItemViewModel : INotifyPropertyChanged
    {
        private int itemNumber;
        private ItemType itemType;

        public event PropertyChangedEventHandler PropertyChanged;

        public int ItemNumber 
        {
            get => itemNumber;
            set
            {
                itemNumber = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ItemNumber)));
            }
        }

        public ItemType ItemType 
        { 
            get => itemType;
            set
            {
                itemType = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ItemType)));
            }
        }
    }
    public enum ItemType
    {
        None,
        NewItem,
        OldItem,
        BrokenItem
    }
}

View.xaml

<UserControl x:Class="WpfDotNetFramework472.CompareSelection"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WpfDotNetFramework472"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <DataGrid 
          AutoGenerateColumns="False"
          ItemsSource="{Binding Items}"
          Width="600">

            <DataGrid.Resources>
                <CollectionViewSource x:Key="ItemTypes" Source="{Binding AllowedItems}" />
            </DataGrid.Resources>

            <DataGrid.Columns>
                <DataGridTextColumn Header="Item Number"
                            Binding="{Binding ItemNumber}"
                            IsReadOnly="True" />
                <DataGridComboBoxColumn Header="Item Type"
                                ItemsSource="{Binding Source={StaticResource ItemTypes}}"
                                SelectedItemBinding="{Binding ItemType, UpdateSourceTrigger=PropertyChanged}">
                    <DataGridComboBoxColumn.ElementStyle>
                        <Style TargetType="{x:Type ComboBox}" BasedOn="{StaticResource {x:Type ComboBox}}">
                        </Style>
                    </DataGridComboBoxColumn.ElementStyle>
                </DataGridComboBoxColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</UserControl>

View.xaml.cs

using System.Windows.Controls;

namespace WpfDotNetFramework472
{
    public partial class CompareSelection : UserControl
    {
        public CompareSelection()
        {
            InitializeComponent();

            DataContext = new CompareSelectionViewModel();
        }
    }
}

The problem seems to be when setting the ElementStyle of the DataGridComboBoxColumn. If you comment out the part of the XAML where the style is set, the ComboBoxes can be set individually.


Solution

  • I have found a workaround. Replacing the ElementStyle in the following way resolves the issue.

    <DataGridComboBoxColumn.ElementStyle>
                        <Style TargetType="{x:Type ComboBox}" BasedOn="{x:Static DataGridComboBoxColumn.DefaultElementStyle}"/>
    </DataGridComboBoxColumn.ElementStyle>
    

    I still don't know why it went wrong using the other style, but I assume it was a implementation quirk of DataGridComboBoxColumn.