How to add a new row to a DataGrid in MVVM format

I have the following DataGrid

 <DataGrid CanUserDeleteRows="True" CanUserAddRows="True" SelectedItem="{Binding SelectedResource, Mode=TwoWay}" ItemsSource="{Binding Path=Resources, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, IsAsync=True}"> ... </<DataGrid> 

I'm using the MVVM pattern to bind to ObservableCollection<ResourceViewModel> Resources , and it works fine. I have a button that adds a new row, and this is done by adding a new ResourceViewModel collection to the Resources collection - fine. Now I want the user to be able to click on the empty last row, and this will automatically create a new record in the DataGrid .

I made sure the DataGrid has CanUserAddRows=True . I made sure that the class in the Resources collection ( ResourceViewModel ) that I am attaching to has a default constructor (no parameters), and I made sure that the type of the collection is not readonly. When the user clicks on the last line, the default constructor starts, but to correctly create a new ResourceViewModel object, a link to the grid of the Resources collection is required ...

I suppose I could use AttachedCommand in the CellBeginEdit event and then add a new ResourceViewModel to the observable collection there, is there a standard way to do this?


Notice I read the following questions and they do not help me


Change It turns out I'm having problems with this due to an error in the WPF DataGrid . See Nigel Spencer's blog . However, fixing it now does not work for me ...

+6
source share
2 answers

I understand that you know how to add new elements to their associated data collection to result in the addition of a new item in DataGrid , and your question is actually related to how you can do it when the user clicks on the last line in the DataGrid . The general way to handle an event in a view model is to create an Attached Property (if one does not already exist) that processes this event for you.

For example, you can create an Attached Property that binds a handler to the corresponding event and another type of ICommand that you could execute when the event handler was called. Then you can write the functionality of this ICommand in your view model (into which you add a new element to your data binding), and the data binds the ICommand implementation to the Attached ICommand Property .

As I am sure you know how to identify Attached Property s, I will not offend you by showing you. Please let me know if I misunderstood or did not understand you.

+3
source

Here's a nested property that registers a command to add rows (if the original collection contains an argument of a general type):

 public static readonly DependencyProperty RegisterAddCommandProperty = DependencyProperty.RegisterAttached("RegisterAddCommand", typeof(bool), typeof(DataGridExtensions), new PropertyMetadata(false, OnRegisterAddCommandChanged)); public static bool GetRegisterAddCommand(DependencyObject obj) { return (bool)obj.GetValue(RegisterAddCommandProperty); } public static void SetRegisterAddCommand(DependencyObject obj, bool value) { obj.SetValue(RegisterAddCommandProperty, value); } static void OnRegisterAddCommandChanged(object sender, DependencyPropertyChangedEventArgs e) { if (sender is DataGrid) { var DataGrid = sender as DataGrid; if ((bool)e.NewValue) DataGrid.CommandBindings.Add(new CommandBinding(AddCommand, AddCommand_Executed, AddCommand_CanExecute)); } } public static readonly RoutedUICommand AddCommand = new RoutedUICommand("AddCommand", "AddCommand", typeof(DataGridExtensions)); static void AddCommand_Executed(object sender, ExecutedRoutedEventArgs e) { var DataGrid = sender as DataGrid; var ItemsSourceType = DataGrid.ItemsSource.GetType(); var ItemType = ItemsSourceType.GetGenericArguments().Single(); DataGrid.Items.Add(Activator.CreateInstance(ItemType)); } static void AddCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = (sender as DataGrid).CanUserAddRows; } 

And then you can apply the command to a button somewhere like this:

 <Button Command="{x:Static Extensions:DataGridExtensions.AddCommand}"/> 

Do not forget to specify the target command.

+1
source

Source: https://habr.com/ru/post/958777/


All Articles