How to have a button in a datagrid template that deletes an item when clicked

I would like to use a datatemplate for my datagrid columns and have a button for each item. I would like the item to be deleted if the user clicks a button. I am using the MVVM pattern. How to do it?

<DataGridTemplateColumn> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <Button Width="50" Content="Remove" Command="{Binding RemoveItemCommand}"/> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> 
+6
source share
3 answers
 public class ItemViewModel { public ItemViewModel() { RemoveCommand = new MyCommand(Remove); } public event EventHandler ItemRemoved; public ICommand RemoveCommand { get; private set; } private void Remove() { // Whatever it takes to remove item from your data store service.Remove(this.Data); var removeItem = ItemRemoved; if (removeItem != null) removeItem(this, EventArgs.Empty); } } public class ListViewModel { public ListViewModel(IEnumerable<ItemViewModel> items) { ItemVMs=new ObservableCollection<ItemViewModel>(items); foreach (var item in ItemVMs) item.ItemRemoved += RemoveSelectedItem; } public ObservableCollection<ItemViewModel> ItemVMs { get; private set; } private void RemoveSelectedItem(object sender, EventArgs e) { var item = sender as ItemViewModel; item.ItemRemoved -= RemoveSelectedItem; ItemVMs.Remove(item); } } 

Each element of RemoveCommand will be bound to its button in your DataGrid. It looks like you already have this part. Make the ListViewModel Property ItemVMs a data source for your DataGrid.

+4
source

View is responsible for this. You can simply use codebehind to control the visibility of user interface elements in response to user actions in the user interface.

Sometimes it's better to be practical than to be harshly dogmatic.


So now that you have edited your question, this becomes a completely different question.

Your DataGrid should be bound to a set of elements.

Your button must be bound to a command in the ViewModel, and CommandParameter must be the Model to which a specific row is bound.

 <DataTemplate> <Button Content="Remove" Command="{Binding DataContext.RemoveItemCommand, ElementName=theWindow}" CommandParameter="{Binding}" /> </DataTemplate> 

Pay attention to some important things here. We need to bind to the ICommand in the ViewModel as part of the template. ViewModel is a DataContext of a window. In this example, the window is called "theWindow" ( x:Name="theWindow" ). Since the binding source is a window, Path must point to the ViewModel in the DataContext property in this window.

We pass the current model to which the DataGrid row is bound to the command. Thus, triival removes it from the collection in the ViewModel.

 public ObservableCollection<Model> Items {get;set;} public ICommand RemoveItemCommand {get;set;} // this method is called when RemoveItemCommand.Execute is called! public void Execute(object parameter) { Items.Remove(parameter as Model); } 

It is assumed that you are using one of the standard delegated ICommand implementations. You can see how trivial to implement this, and since the collection is observable, after clicking the button and deleting the model, the DataGrid will be notified of the collection change and delete this row.

+4
source

You should probably use standard routed events in the Click event of a button instead of a command. A click event will allow you to get information about which control was clicked, and then you can also easily get the parent element of the button to remove that element.

+2
source

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


All Articles