Click here to Skip to main content
15,894,343 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
Hi everyone,

maybe someone has come around the following situation:

I have placed a datagrid inside a tabcontrol content template.

When performing the following steps, an exception is caused:

* I go into the tab with the datagrid inside
* edit an text item in the datagrid but leave the caret in the field
* Switch to another tab
* Switch back to the tab with the edited datagrid

The exception is as follows:

C++
InvalidOperationException {"'DeferRefresh' is not allowed during an AddNew or EditItem transaction."}


From that I take that I would have to end the editing mode (probably DataGrid.CancelEdit()) manually. But how do I do this in MVVM?

Many thanks!
Posted

This is not a solution, merely a workaround. I've created an attached property for the datagrid that will be linked to a notifying bool property in the viewmodel. When flipping that bool, the editing mode of the datagrid is ended. In my code, I'm flipping that bool when the SelectedItem of the tabcontrol which contains the datagrid changes.

public class DataGridBehaviors
{
  // The purpose of this property is to be able to signal a datagrid manually 
  // to end its editing mode. When you have datagrid on a tab inside a tabcontrol
  // based on content templates and a observablecollection as source, it may cause an
  // exception when leaving and reentering it in editing mode (while the caret is in 
  // a cell)
#region EndEditing Property
  // When starting this property, I first tried to generate an action right here and 
  // call it from the viewmodel. This didn't work out so I went for having a simple
  // bool which - when flipped - signals the datagrid to stop the editing mode.
  
  public static void SetEndEditing(DependencyObject obj, bool a)
  {
    obj.SetValue(EndEditingProperty, a);
  }

  public static bool GetEndEditing(DependencyObject obj)
  {
    return (bool) obj.GetValue(EndEditingProperty);
  }

  public static readonly DependencyProperty EndEditingProperty
    = DependencyProperty.RegisterAttached(
    "EndEditing",
    typeof(bool),
    typeof(DataGridBehaviors),
    new PropertyMetadata(new PropertyChangedCallback(EndEditingChanged))
  );

  private static void EndEditingChanged(DependencyObject sender, 
    DependencyPropertyChangedEventArgs e)
  {
    var dg = sender as DataGrid;
    if (null == dg) return;

    // CancelEdit is not sufficient
    dg.CancelEdit();
    // this has also to be called to really end the editing mode
    dg.CommitEdit();
  }
#endregion
}
 
Share this answer
 
The problem you've encountered, isn't the problem that you think it is. Basically, when you switch tabs in WPF, the old data context and view are destroyed, and a new one is created. If you download Cinch[^] and take a look at the WPF_Demo.zip project, you will find a TabControlEx class; use this in place of your TabControl and this problem should go away.
 
Share this answer
 
Comments
Doc Lobster 3-Nov-12 5:37am    
Hello Pete, thank you for your answer. I tried replacing the standard tab control with the one from the Cinch v2 demo, however the exception stays the same.

I also tried to reproduce the problem with a simple (no tab header and content templates) code-behind demo project, which didn't show the exception. The idea that the view is destroyed on a tab change sounded a bit strange to me, so I added two non-bound radioboxes in a tab of that demo project. Their values are kept after tab switching away an back.

As I already spent quite some time on this, I'm now ready to avoid this by switching to another UI design. :(

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900