WPF DataGrid ComboBox causes InvalidOperationException
Asked Answered
D

2

6

I am getting an InvalidOperationException('DeferRefresh' is not allowed during an AddNew or EditItem transaction.) from my datagrid when I try to edit the value of a combo box column. The items I am showing all have a reference to one other item in the same list so this is what I am using the combobox for. It is bound to the same collection as the datagrid is. My application I am working on is targetting .NET 3.5, but I have put together an example that is exactly the same in .NET 4 since the datagrid is built in. Here is the code for items in the datagrid:

public class TestItem : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private void RaisePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    private int m_ID;
    private string m_Name;
    private int m_OppositeID;

    public int ID
    {
        get { return m_ID; }
        set
        {
            m_ID = value;
            RaisePropertyChanged("ID");
        }
    }
    public string Name
    {
        get { return m_Name; }
        set
        {
            m_Name = value;
            RaisePropertyChanged("Name");
        }
    }
    public int OppositeID
    {
        get { return m_OppositeID; }
        set
        {
            m_OppositeID = value;
            RaisePropertyChanged("OppositeID");
        }
    }

    public TestItem(int id, string name, int oppID)
    {
        ID = id;
        Name = name;
        OppositeID = oppID;
    }
}

This is the code in my window:

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private void RaisePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    private ObservableCollection<TestItem> m_Items;

    public ObservableCollection<TestItem> Items
    {
        get { return m_Items; }
        set
        {
            m_Items = value;
            RaisePropertyChanged("Items");
        }
    }

    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;

        Items = new ObservableCollection<TestItem>();

        Items.Add(new TestItem(0, "Fixed", 0));
        Items.Add(new TestItem(1, "Left Side", 2));
        Items.Add(new TestItem(2, "Right Side", 1));
    }
}

and finally my xaml:

<Window x:Class="DataGrid_Combo_Test.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
    <Grid>
        <DataGrid ItemsSource="{Binding Path=Items}" AutoGenerateColumns="False">
            <DataGrid.Resources>
                <Style x:Key="ItemsSourceStyle" TargetType="ComboBox">
                    <Setter Property="ItemsSource" Value="{Binding Path=DataContext.Items, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"/>
                </Style>
            </DataGrid.Resources>
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding Path=ID}" Header="ID" Width="*"/>
                <DataGridTextColumn Binding="{Binding Path=Name}" Header="Name" Width="*"/>
                <DataGridComboBoxColumn Header="Opposite Item" Width="*" DisplayMemberPath="Name" SelectedValuePath="ID" SelectedValueBinding="{Binding Path=OppositeID}" ElementStyle="{StaticResource ItemsSourceStyle}" EditingElementStyle="{StaticResource ItemsSourceStyle}"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

Thanks in advance for any assistance you can offer!

Determinism answered 11/8, 2010 at 18:42 Comment(2)
This seems to be connected to the issues reported on Connect(connect.microsoft.com/VisualStudio/feedback/details/591125/…) and the MSDN Forums(social.msdn.microsoft.com/Forums/en-US/wpf/thread/…); but this is by far the most elegant workaround!Dachi
I had this problem because I had mistakenly bound my DataGrid and DataGridComboBoxColumn to the same collection.Gottfried
D
3

I found out how to fix this issue.

I created a CollectionViewSource like this in my Window.Resources:

<Window.Resources>
    <CollectionViewSource x:Key="itemSource" Source="{Binding Path=Items}"/>
</Window.Resources>

Then changed my combobox column definition to the following:

<DataGridComboBoxColumn Header="Opposite Item" Width="*" DisplayMemberPath="Name" SelectedValuePath="ID" SelectedValueBinding="{Binding Path=OppositeID}" ItemsSource="{Binding Source={StaticResource itemSource}}"/>
Determinism answered 12/8, 2010 at 2:37 Comment(0)
P
2

Try following sequence before calling Refersh on CollectionView or DataGridXYZ.Items

DataGridX.CommitEdit();

DataGridX.CancelEdit();

Worked for me.

Pistachio answered 8/11, 2011 at 12:27 Comment(1)
The posted code was just a short demonstration of the problem. The real application uses mvvm and this approach would mean attaching event handlers and such.Determinism

© 2022 - 2024 — McMap. All rights reserved.