2010-08-11 18 views
6

Je reçois une InvalidOperationException ('DeferRefresh' n'est pas autorisé lors d'une transaction AddNew ou EditItem.) De mon DataGrid lorsque j'essaie de modifier la valeur d'une colonne de zone de liste déroulante. Les éléments que je montre tous ont une référence à un autre élément de la même liste, c'est pour cela que j'utilise la combobox. Il est lié à la même collection que le DataGrid. L'application sur laquelle je travaille est en train de cibler .NET 3.5, mais j'ai rassemblé un exemple qui est exactement le même dans .NET 4 depuis le datagrid. Voici le code des éléments de la grille de données:WPF DataGrid ComboBox provoque InvalidOperationException

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; 
    } 
} 

Ceci est le code dans ma fenêtre:

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)); 
    } 
} 

et enfin mon 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> 

Merci d'avance pour toute aide que vous pouvez offrir!

+1

Cela semble être lié aux problèmes signalés sur Connect (https://connect.microsoft.com/VisualStudio/feedback/details/591125/datagrid-exception-on-validation-failure-deferrefresh-is-not-allowed) et les Forums MSDN (http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/187b2b8f-d403-4bf3-97ad-7f93b4385cdf/); mais c'est de loin la solution de contournement la plus élégante! –

+0

J'ai rencontré ce problème car j'ai lié ma DataGrid et DataGridComboBoxColumn par erreur à la même collection. – Maxence

Répondre

3

J'ai découvert comment résoudre ce problème.

J'ai créé un CollectionViewSource comme ça dans mes Window.Resources:

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

ensuite changé ma définition de la colonne combobox à ce qui suit:

<DataGridComboBoxColumn Header="Opposite Item" Width="*" DisplayMemberPath="Name" SelectedValuePath="ID" SelectedValueBinding="{Binding Path=OppositeID}" ItemsSource="{Binding Source={StaticResource itemSource}}"/> 
2

Essayez séquence suivante avant d'appeler Refersh sur CollectionView ou DataGridXYZ.Items

DataGridX.CommitEdit(); 

DataGridX.CancelEdit(); 

A travaillé pour moi.

+0

Le code affiché n'était qu'une courte démonstration du problème. L'application réelle utilise mvvm et cette approche impliquerait d'attacher des gestionnaires d'événements et autres. – aalex675