I had a little bit of trouble understanding what you wrote, but I believe you're either wanting to remove a given row when the delete button on that row is clicked, or, only when it is the selected row.
As you didn't provide your model, I created my own called RowData
. You should be able to translate my answer to your own circumstance though. I did attempt to keep your variable names.
Binding commands requires routing. So to make this simple, I've provided the CommandHandler
. It is short, simple, and reusable. I originally sourced it from yo chauhan, here. It allows you to attach a function/ action, and also supply conditions on whether it can execute.
I've updated your XAML to have a bit of a cleaner structure for MVVM. From my experience, I feel it makes the code clearer, and maintains MVVM.
I've then tied it altogether on the MainWindow
, but you can place it anywhere, provided it has the data context. You will notice in the DeleteRow
method of MainWindow
, there are two sections of code. The first deletes the SelectedRow
, which is maintained by MainWindow
; it also means, you could have a different row selected, and click any button, and it will remove the highlighted row. The second section removes the given row which has been passed to the parent (meaning, the row which owns the delete button which you pressed).
RowDataModel:
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Input;
public class RowData : INotifyPropertyChanged
{
private MainWindow _parent;
public RowData(MainWindow parent)
{
_parent = parent;
}
private void NotifyChanged([CallerMemberName] string property = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
public event PropertyChangedEventHandler PropertyChanged;
private decimal _quantidade;
public decimal Quantidade
{
get { return _quantidade; }
set
{
_quantidade = value;
NotifyChanged(nameof(Quantidade));
}
}
private string _descricao;
public string Descricao
{
get { return _descricao; }
set
{
_descricao = value;
NotifyChanged(nameof(Descricao));
}
}
private decimal _valorVenda;
public decimal ValorVenda
{
get { return _valorVenda; }
set
{
_valorVenda = value;
NotifyChanged(nameof(ValorVenda));
}
}
private ICommand _delete;
public ICommand Delete
{
get => _delete ?? (_delete = new CommandHandler(() => DeleteRow(), () => CanDelete()));
}
private void DeleteRow()
{
if (_parent.DeleteRow(this))
{
MessageBox.Show("Deleted!");
}
else
{
MessageBox.Show("Did not delete.");
}
}
private bool CanDelete()
{
return true;
}
}
CommandHandler:
using System;
using System.Windows.Input;
public class CommandHandler : ICommand
{
private Action _action;
private Func<bool> _canExecute;
/// <summary>
/// Creates instance of the command handler
/// </summary>
/// <param name="action">Action to be executed by the command</param>
/// <param name="canExecute">A boolean property to containing current permissions to execute the command</param>
public CommandHandler(Action action, Func<bool> canExecute)
{
_action = action;
_canExecute = canExecute;
}
/// <summary>
/// Connects CanExecuteChanged event
/// </summary>
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
/// <summary>
/// Force checking if execute is allowed
/// </summary>
/// <param name="parameter"></param>
/// <returns></returns>
public bool CanExecute(object parameter)
{
return _canExecute.Invoke();
}
public void Execute(object parameter)
{
_action();
}
}
XAML:
<ListView ItemsSource="{Binding Carrinho}" SelectedItem="{Binding SelectedRow}">
<ListView.View>
<GridView AllowsColumnReorder="True">
<GridViewColumn Header="Quantidade" Width="100">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Quantidade}" Foreground="#00b503" Margin="0 40 5 0"
FontSize="14" TextWrapping="Wrap" HorizontalAlignment="Left" FontWeight="UltraBold"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Descricao" Width="100">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Descricao}" Foreground="#00b503" Margin="10 40 10 10"
FontSize="12" TextWrapping="WrapWithOverflow" Width="170" TextAlignment="Left" FontWeight="Bold"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="ValdorVenda" Width="200">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding ValorVenda, StringFormat=N2}" Foreground="#00b503" Margin="10 40 10 10"
FontSize="12" TextWrapping="Wrap" HorizontalAlignment="Right" FontWeight="UltraBold" Height="25"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="100">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button Command="{ Binding Delete}" Background="{x:Null}" BorderBrush="{x:Null}"
Margin="0 20 0 0" HorizontalAlignment="Left">
<Rectangle Fill="Red" Width="20" Height="20" Margin="10"/>
</Button>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
MainWindow:
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
Generate();
InitializeComponent();
DataContext = this;
}
private void Generate()
{
Carrinho = new ObservableCollection<RowData>();
for (int i = 0; i < 100; i++)
{
Carrinho.Add(new RowData(this)
{
Descricao = "A description",
Quantidade = 10m + (i * 2.2m),
ValorVenda = 100m + (i * 1.3m)
});
}
NotifyChanged(nameof(Carrinho));
}
private void NotifyChanged([CallerMemberName] string property = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
private ObservableCollection<RowData> _carrinho;
public event PropertyChangedEventHandler PropertyChanged;
public ObservableCollection<RowData> Carrinho
{
get { return _carrinho; }
set
{
_carrinho = value;
NotifyChanged(nameof(Carrinho));
}
}
private RowData _selectedRow;
public RowData SelectedRow
{
get { return _selectedRow; }
set
{
_selectedRow = value;
NotifyChanged(nameof(SelectedRow));
}
}
public bool DeleteRow(RowData child)
{
// Removing Selected Row
//if (SelectedRow != null)
//{
// var temp = new RowData(this)
// {
// Descricao = SelectedRow.Descricao,
// Quantidade = SelectedRow.Quantidade,
// ValorVenda = SelectedRow.ValorVenda
// };
// Carrinho.Remove(SelectedRow);
// SelectedRow = null;
// return !Carrinho.Contains(temp);
//}
// Removing Row where delete was clicked
if(child != null)
{
Carrinho.Remove(child);
return !Carrinho.Contains(child);
}
return false;
}
}