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 thi开发者_高级运维ngs 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();
}
}
精彩评论