English 中文(简体)
WPF DataGrid: handling CanUserAddRows=true cleanly with MVVM
原标题:

I ve been looking into MVVM lately, and after I discovered Caliburn.Micro things have been pretty swell; I m still in the early learning stages, but I belive I have an OK feel for the MVVM basics.

I m bumping into issues with WPF DataGrid, though - and it s pretty much the same issues that I had with WinForms DataGridView: how the heck do you handle CanUserAddRows=true in-grid item adding cleanly?

I obviously don t want to add DataGrid-specific hacks to my ViewModel, since it ideally should be repurposable for other View controls. At the same time, I d like to be able to get a notification when a new row item has been added, so I can persist it right away.

I m binding the DataGrid to a BindableCollection<FooModel> FooItems - with a clean MVVM design, if I understand things correctly, I would be able to handle FooItems.CollectionChanged and react to Add/Remove events. However, the DataGrid fires the Add event as soon as a default-constructed item is added - this is obviously not the right time to persist the object!

After a lot of googling and digging through StackOverflow, I m getting the impression that DataGrid is being utterly retarded in how it s firing the Add/Remove events. People who use it with CanUserAddRows=true seem to only work on in-memory collections, where people who persist data seem to use separate input fields + buttons Commands to add new items.

My FooModel implements INotifyPropertyChanged but not IEditableObject - as far as I can tell that shouldn t be the problem, though, since IEO seems related to property edit/undo, whereas my problem is with when the Add event is fired...

So, what do you do to handle in-grid editing cleanly?

问题回答

It sounds like the WPF DataGrid behaves in much the same way as the WinForms DataGridView, in that it creates an item in the data source as soon as the user begins entering into the new row . Subsequent edits would result in changes to the properties of the new item in the collection.

If you were to use BindingList<FooModel> instead, you get the additional event called ListChanged - providing your FooModel type implements INotifyPropertyChanged, the event will fire when the properties of the item are changed (as well as when items are added/removed from the collection).

Hope this helps!

I know it s been a long time since this was asked but I m working on something similar now and thought I d post my solution. You may consider this a hack but it s the best way I could figure to get DataGrid to tell me when it was out of edit mode (for my own reasons).

I looked through the DataGrid code and found the closest thing to end edit I could override, which turns out to be OnExecutedCommitEdit(). I then just raise an event after that function finishes. When my event subscriber gets called DataGrid is no longer in edit mode and I can do whatever I need to it. Here s the code:

/// <summary>
/// Deriving a new DataGrid because we need an event to tell us when editing is complete.
/// </summary>
public class DataGridMod : DataGrid
{
   public delegate void EditCompletedDelegate();
   public EditCompletedDelegate EditCompleted;

   public DataGridMod() { }

   protected override void OnExecutedCommitEdit(ExecutedRoutedEventArgs e)
   {
      base.OnExecutedCommitEdit(e);

      if (EditCompleted != null)
         EditCompleted();
   }
}




相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签