Hi Reza,
you must iterate thru SelectedItems in descending order and remove form items collection (not from SelectedItems collection). I changed your demo. try it.
XAML:
<Window x:Class="WpfApp1.Window098"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp098"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
mc:Ignorable="d"
Title="RezaJafery_220115" Height="450" Width="900">
<Window.DataContext>
<local:ViewModel/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DataGrid x:Name="BillDataGrid"
HeadersVisibility="Column"
CanUserAddRows="False"
CanUserDeleteRows="False"
EnableRowVirtualization="True"
AutoGenerateColumns="False"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="5">
<i:Interaction.Behaviors>
<local:DataGridBehavior/>
</i:Interaction.Behaviors>
<DataGrid.Columns>
<DataGridTextColumn Header="NO" Binding="{Binding NO}" Width="SizeToHeader"/>
<DataGridTextColumn Header="ID_Serial" Binding="{Binding ID_Serial}" Width="SizeToHeader"/>
<DataGridTextColumn Header="ProductsOrServicesDescription" Binding="{Binding ProductsOrServicesDescription}" Width="115"/>
<DataGridTextColumn Header="Quantity" Binding="{Binding Quantity}" Width="SizeToHeader"/>
<DataGridTextColumn Header="UnitOfMeasurement" Binding="{Binding UnitOfMeasurement}" Width="SizeToHeader"/>
<DataGridTextColumn Header="UnitPrice" Binding="{Binding UnitPrice}" Width="SizeToHeader"/>
<DataGridTextColumn Header="Discount" Binding="{Binding Discount}" Width="SizeToHeader"/>
<DataGridTextColumn Header="TaxDutyVat" Binding="{Binding TaxDutyVat}" Width="SizeToHeader"/>
<DataGridTextColumn Header="GuaranteeOrWarrantyPeriod" Binding="{Binding GuaranteeOrWarrantyPeriod}" Width="SizeToHeader"/>
<DataGridTextColumn Header="TotalAmount" Binding="{Binding TotalAmount}" Width="SizeToHeader"/>
</DataGrid.Columns>
</DataGrid>
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right">
<Button Content="Add New Row" Command="{Binding}" CommandParameter="AddNewRow" Width="100" Margin="5"/>
<Button Content="Delete selected rows" Command="{Binding}" CommandParameter="DeleteSelectedRows" Width="100" Margin="5"/>
</StackPanel>
</Grid>
</Window>
and code:
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interactivity;
namespace WpfApp098
{
public class ViewModel : ICommand
{
public DataGrid BillDataGrid { get; set; }
int NO;
public void AddBlankRow()
{
List<object> DefaultRow = new List<object>();
DefaultRow DR = new DefaultRow();
DR.NO = (++NO).ToString(); // "";
DR.ID_Serial = "";
DR.ProductsOrServicesDescription = "";
DR.Quantity = "";
DR.UnitOfMeasurement = "";
DR.UnitPrice = "";
DR.Discount = "";
DR.TaxDutyVat = "";
DR.GuaranteeOrWarrantyPeriod = "";
DR.TotalAmount = "";
for (int i = 0; i < BillDataGrid.Items.Count; i++)
{
DefaultRow.Add(BillDataGrid.Items[i]);
}
DefaultRow.Add(DR);
BillDataGrid.ItemsSource = DefaultRow;
}
private void DeleteSelectedRows_Button_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
switch (BillDataGrid.SelectedItems.Count > 0)
{
case false:
break;
default:
List<object> DefaultRow = new List<object>();
for (int i = 0; i < BillDataGrid.Items.Count; i++)
{
DefaultRow.Add(BillDataGrid.Items[i]);
}
for (int i = BillDataGrid.SelectedItems.Count - 1; i >= 0; i--)
{
DefaultRow.RemoveAt(BillDataGrid.Items.IndexOf(BillDataGrid.SelectedItems[i]));
}
BillDataGrid.ItemsSource = DefaultRow;
break;
}
}
//private void DeleteSelectedRows_Button_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
//{
// switch (BillDataGrid.SelectedItems.Count > 0)
// {
// case false:
// break;
// default:
// ;
// for (int i = 0; i < BillDataGrid.SelectedItems.Count; i++)
// {
// BillDataGrid.Items.Remove(BillDataGrid.SelectedItems[i]);
// }
// break;
// }
//}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter) => true;
public void Execute(object parameter)
{
switch (parameter.ToString())
{
case "AddNewRow": AddBlankRow(); break;
case "DeleteSelectedRows": DeleteSelectedRows_Button_PreviewMouseLeftButtonDown(null, null); break;
default: break;
}
}
}
public class DefaultRow
{
public string NO { get; set; }
public string ID_Serial { get; set; }
public string ProductsOrServicesDescription { get; set; }
public string Quantity { get; set; }
public string UnitOfMeasurement { get; set; }
public string UnitPrice { get; set; }
public string Discount { get; set; }
public string TaxDutyVat { get; set; }
public string GuaranteeOrWarrantyPeriod { get; set; }
public string TotalAmount { get; set; }
}
public class DataGridBehavior : Behavior<DataGrid>
{
protected override void OnAttached() =>
AssociatedObject.Loaded += (s, e) =>
((ViewModel)AssociatedObject.DataContext).BillDataGrid = AssociatedObject;
}
}
A better solution is to use collection and ItemsSource. Try following demo:
XAML:
<Window x:Class="WpfApp1.Window099"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp099"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
mc:Ignorable="d"
Title="RezaJafery_220115" Height="450" Width="900">
<Window.DataContext>
<local:ViewModel/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DataGrid ItemsSource="{Binding View}"
HeadersVisibility="Column"
CanUserAddRows="False"
CanUserDeleteRows="False"
EnableRowVirtualization="True"
AutoGenerateColumns="False"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="5">
<i:Interaction.Behaviors>
<local:DataGridBehavior/>
</i:Interaction.Behaviors>
<DataGrid.Columns>
<DataGridTextColumn Header="NO" Binding="{Binding NO}" Width="SizeToHeader"/>
<DataGridTextColumn Header="ID_Serial" Binding="{Binding ID_Serial}" Width="SizeToHeader"/>
<DataGridTextColumn Header="ProductsOrServicesDescription" Binding="{Binding ProductsOrServicesDescription}" Width="115"/>
<DataGridTextColumn Header="Quantity" Binding="{Binding Quantity}" Width="SizeToHeader"/>
<DataGridTextColumn Header="UnitOfMeasurement" Binding="{Binding UnitOfMeasurement}" Width="SizeToHeader"/>
<DataGridTextColumn Header="UnitPrice" Binding="{Binding UnitPrice}" Width="SizeToHeader"/>
<DataGridTextColumn Header="Discount" Binding="{Binding Discount}" Width="SizeToHeader"/>
<DataGridTextColumn Header="TaxDutyVat" Binding="{Binding TaxDutyVat}" Width="SizeToHeader"/>
<DataGridTextColumn Header="GuaranteeOrWarrantyPeriod" Binding="{Binding GuaranteeOrWarrantyPeriod}" Width="SizeToHeader"/>
<DataGridTextColumn Header="TotalAmount" Binding="{Binding TotalAmount}" Width="SizeToHeader"/>
</DataGrid.Columns>
</DataGrid>
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right">
<Button Content="Add New Row" Command="{Binding}" CommandParameter="AddNewRow" Width="100" Margin="5"/>
<Button Content="Delete selected rows" Command="{Binding}" CommandParameter="DeleteSelectedRows" Width="100" Margin="5"/>
</StackPanel>
</Grid>
</Window>
And code:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Interactivity;
namespace WpfApp099
{
public class ViewModel : ICommand
{
public DataGrid BillDataGrid { get; set; }
int NO;
public ViewModel() => cvs.Source = col;
ObservableCollection<DefaultRow> col = new ObservableCollection<DefaultRow>();
private CollectionViewSource cvs = new CollectionViewSource();
public ICollectionView View { get => cvs.View; }
public void AddBlankRow()
{
DefaultRow DR = new DefaultRow();
DR.NO = (++NO).ToString(); // "";
DR.ID_Serial = "";
DR.ProductsOrServicesDescription = "";
DR.Quantity = "";
DR.UnitOfMeasurement = "";
DR.UnitPrice = "";
DR.Discount = "";
DR.TaxDutyVat = "";
DR.GuaranteeOrWarrantyPeriod = "";
DR.TotalAmount = "";
col.Add(DR);
}
private void DeleteSelectedRows_Button_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
switch (BillDataGrid.SelectedItems.Count > 0)
{
case false:
break;
default:
List<DefaultRow> cache = new List<DefaultRow>();
foreach (var item in BillDataGrid.SelectedItems) cache.Add((DefaultRow)item);
foreach (DefaultRow item in cache) col.Remove(item);
break;
}
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter) => true;
public void Execute(object parameter)
{
switch (parameter.ToString())
{
case "AddNewRow": AddBlankRow(); break;
case "DeleteSelectedRows": DeleteSelectedRows_Button_PreviewMouseLeftButtonDown(null, null); break;
default: break;
}
}
}
public class DefaultRow
{
public string NO { get; set; }
public string ID_Serial { get; set; }
public string ProductsOrServicesDescription { get; set; }
public string Quantity { get; set; }
public string UnitOfMeasurement { get; set; }
public string UnitPrice { get; set; }
public string Discount { get; set; }
public string TaxDutyVat { get; set; }
public string GuaranteeOrWarrantyPeriod { get; set; }
public string TotalAmount { get; set; }
}
public class DataGridBehavior : Behavior<DataGrid>
{
protected override void OnAttached() =>
AssociatedObject.Loaded += (s, e) =>
((ViewModel)AssociatedObject.DataContext).BillDataGrid = AssociatedObject;
}
}