Hi,@vitaminchik. For updating the row number when adding and deleting items, you could create a custom property DisplayRowNumber
and use local : DataGridBehavior. DisplayRowNumber = "True"
in DataGrid.
You can refer to the code below.
<Window.Resources>
<local:SelectedItemToItemsSource x:Key="SelectedItemToItemsSource"/>
<DataTemplate x:Key="UserGrid">
<Border Background="Chocolate" BorderBrush="Black" BorderThickness="1" CornerRadius="5" >
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="No1" Grid.Row="1" Grid.Column="0"/>
<TextBlock Text="No2" Grid.Row="2" Grid.Column="0"/>
<TextBlock Text="Name" Grid.Row="3" Grid.Column="0"/>
<TextBlock Text="Description" Grid.Row="4" Grid.Column="0"/>
<TextBlock Text="WorkersCategory" Grid.Row="5" Grid.Column="0"/>
<TextBlock Text="Time" Grid.Row="6" Grid.Column="0"/>
<TextBlock Text="PriceRate" Grid.Row="7" Grid.Column="0"/>
<TextBlock Text="Specifications" Grid.Row="8" Grid.Column="0"/>
<TextBox Text="{Binding No1, BindingGroupName=Group1, UpdateSourceTrigger=Explicit}" Grid.Column="1" Grid.Row="1"/>
<TextBox Text="{Binding No2, BindingGroupName=Group1, UpdateSourceTrigger=Explicit}" Grid.Column="1" Grid.Row="2"/>
<TextBox Text="{Binding Name, BindingGroupName=Group1, UpdateSourceTrigger=Explicit}" Grid.Column="1" Grid.Row="3"/>
<TextBox Text="{Binding Description, BindingGroupName=Group1, UpdateSourceTrigger=Explicit}" Grid.Column="1" Grid.Row="4"/>
<TextBox Text="{Binding WorkersCategory, BindingGroupName=Group1, UpdateSourceTrigger=Explicit}" Grid.Column="1" Grid.Row="5"/>
<TextBox Text="{Binding Time, BindingGroupName=Group1, UpdateSourceTrigger=Explicit}" Grid.Column="1" Grid.Row="6"/>
<TextBox Text="{Binding PriceRate, BindingGroupName=Group1, UpdateSourceTrigger=Explicit}" Grid.Column="1" Grid.Row="7"/>
<TextBox Text="{Binding Specifications, BindingGroupName=Group1, UpdateSourceTrigger=Explicit}" Grid.Column="1" Grid.Row="8"/>
<StackPanel Orientation="Horizontal" Grid.Row="11" Grid.ColumnSpan="2" HorizontalAlignment="Right" Margin="5,5,5,5">
<Button Foreground="White" Background="Green" Content="Cancel" Command="{Binding DataContext.CancelCommand, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" Margin="4,0"/>
<Button Foreground="White" Background="Green" Content="Delete" Command="{Binding DataContext.DeleteUserCommand, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" Margin="4,0"/>
<Button Foreground="White" Background="Green" Content="Save" Command="{Binding DataContext.SaveCommand, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" Margin="4,0"/>
<Button Foreground="White" Background="Green" Content="Add" Command="{Binding DataContext.AddCommand, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" Margin="4,0"/>
</StackPanel>
</Grid>
</Border>
</DataTemplate>
</Window.Resources>
<Grid Margin="0,0,0,-1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="7*"/>
<ColumnDefinition Width="3*"/>
</Grid.ColumnDefinitions>
<GroupBox Header="Data" HorizontalAlignment="Center" VerticalAlignment="Center" Height="383" Margin="5,5,5,5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DataGrid x:Name="dg1" ItemsSource="{Binding Infos}" SelectedItem="{Binding SelectedInfo}" CanUserAddRows="False" local:DataGridBehavior.DisplayRowNumber="True"
CanUserDeleteRows="False" SelectionMode="Single" SelectedIndex="{Binding SelectedIndex}" VerticalAlignment="Top"
AutoGenerateColumns="False" Margin="5,5,5,5">
<DataGrid.Columns>
<DataGridTextColumn Header="No1" Binding="{Binding No1}"/>
<DataGridTextColumn Header="No2" Binding="{Binding No2}"/>
<DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
<DataGridTextColumn Header="Description" Binding="{Binding Description}"/>
<DataGridTextColumn Header="WorkersCategory" Binding="{Binding WorkersCategory}"/>
<DataGridTextColumn Header="Time" Binding="{Binding Time}"/>
<DataGridTextColumn Header="PriceRate" Binding="{Binding PriceRate}"/>
<DataGridTextColumn Header="Specifications" Binding="{Binding Specifications}"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</GroupBox>
<ItemsControl BindingGroup="{Binding UpdateBindingGroup, Mode=OneWay}" VerticalAlignment="Top" Margin="5,5,5,5" Grid.Column="1"
ItemTemplate="{StaticResource UserGrid}" ItemsSource="{Binding SelectedInfo, Converter={StaticResource SelectedItemToItemsSource}}" />
</Grid>
Codebedhind:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Data;
using System.Data.SQLite;
using System.Globalization;
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
using System.Xml.Linq;
namespace CURDdemo
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DatabaseLayer.LoadData();
this.DataContext = new ViewModelUser();
}
}
public class ViewModelUser : ViewModelBase
{
public ViewModelUser()
{
personnel = new PersonnelBusinessObject();
personnel.InfoChanged += new EventHandler(personnel_InfoChanged);
UpdateBindingGroup = new BindingGroup { Name = "Group1" };
CancelCommand = new RelayCommand(DoCancel);
SaveCommand = new RelayCommand(DoSave);
AddCommand = new RelayCommand(AddUser);
DeleteUserCommand = new RelayCommand(DeleteUser);
}
PersonnelBusinessObject personnel;
private ObservableCollection<Info> _Info;
public ObservableCollection<Info> Infos
{
get
{
_Info = new ObservableCollection<Info>(personnel.GetInfos());
return _Info;
}
}
public int SelectedIndex { get; set; }
object _SelectedInfo;
public object SelectedInfo
{
get
{
return _SelectedInfo;
}
set
{
if (_SelectedInfo != value)
{
_SelectedInfo = value;
OnPropertyChanged("SelectedInfo");
}
}
}
private BindingGroup _UpdateBindingGroup;
public BindingGroup UpdateBindingGroup
{
get
{
return _UpdateBindingGroup;
}
set
{
if (_UpdateBindingGroup != value)
{
_UpdateBindingGroup = value;
OnPropertyChanged("UpdateBindingGroup");
}
}
}
void personnel_InfoChanged(object sender, EventArgs e)
{
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
OnPropertyChanged("Infos");
}));
}
public RelayCommand CancelCommand { get; set; }
public RelayCommand SaveCommand { get; set; }
public RelayCommand AddCommand { get; set; }
public RelayCommand DeleteUserCommand { get; set; }
void DoCancel(object param)
{
UpdateBindingGroup.CancelEdit();
if (SelectedIndex == -1) //This only closes if new - just to show you how CancelEdit returns old values to bindings
SelectedInfo = null;
}
void DoSave(object param)
{
UpdateBindingGroup.CommitEdit();
var info = SelectedInfo as Info;
if (SelectedIndex == -1)
{
personnel.AddInfo(info);
OnPropertyChanged("Employee"); // Update the list from the data source
}
else
personnel.UpdateInfo(info);
SelectedInfo = null;
}
void AddUser(object param)
{
SelectedInfo = null; // Unselects last selection. Essential, as assignment below won't clear other control's SelectedItems
var info = new Info();
SelectedInfo = info;
}
void DeleteUser(object parameter)
{
var info = SelectedInfo as Info;
if (SelectedIndex != -1)
{
personnel.DeleteInfo(info);
OnPropertyChanged("Employee"); // Update the list from the data source
}
else
SelectedInfo = null; // Simply discard the new object
}
}
public static class DatabaseLayer
{
public static void LoadData()
{
SQLiteConnection.CreateFile("MyDatabase.sqlite");
SQLiteConnection m_dbConnection = new SQLiteConnection("Data Source=MyDatabase.sqlite");
m_dbConnection.Open();
string sql = "create table MyData (Id INTEGER PRIMARY KEY AUTOINCREMENT, No1 varchar(20), No2 varchar(20), Name varchar(20) ,Description varchar(20) ," +
"WorkersCategory varchar(20),Time varchar(20),PriceRate varchar(20),Specifications varchar(20)) ";
SQLiteCommand command = new SQLiteCommand(sql, m_dbConnection);
command.ExecuteNonQuery();
sql = "INSERT INTO MyData(No1,No2, Name,Description,WorkersCategory,Time,PriceRate,Specifications) VALUES('NO1 ', 'NO2','NAME1','D1','TEXT','TEXT','TEXT','TEXT')";
command = new SQLiteCommand(sql, m_dbConnection);
command.ExecuteNonQuery();
sql = "INSERT INTO MyData(No1,No2, Name,Description,WorkersCategory,Time,PriceRate,Specifications) VALUES('NO1 ', 'NO2','NAME2','D2','TEXT','TEXT','TEXT','TEXT')";
command = new SQLiteCommand(sql, m_dbConnection);
command.ExecuteNonQuery();
m_dbConnection.Close();
}
public static List<Info> GetInfoFromDatabase()
{
try
{
SQLiteConnection m_dbConnection = new SQLiteConnection("Data Source=MyDatabase.sqlite");
SQLiteCommand sqlCom = new SQLiteCommand("Select * From MyData", m_dbConnection);
SQLiteDataAdapter sda = new SQLiteDataAdapter(sqlCom);
DataTable dt = new DataTable();
sda.Fill(dt);
var Employee = new List<Info>();
foreach (DataRow row in dt.Rows)
{
var obj = new Info()
{
Id = Convert.ToInt32(row["Id"]),
No1 = (string)row["No1"],
No2 = (string)row["No2"],
Name = (string)(row["Name"]),
Description = (string)row["Description"],
WorkersCategory = (string)(row["WorkersCategory"]),
Time = (string)(row["Time"]),
PriceRate = (string)(row["PriceRate"]),
Specifications = (string)(row["Specifications"]),
// Equipment = (ObservableCollection<Equi>)row["Equipment"],
};
Employee.Add(obj);
m_dbConnection.Close();
}
return Employee;
}
catch (Exception ex)
{
throw ex;
}
}
internal static int InsertInfo(Info info)
{
try
{
const string query = "INSERT INTO MyData(No1,No2, Name,Description,WorkersCategory,Time,PriceRate,Specifications) VALUES(@No1, @No2,@Name,@Description,@WorkersCategory,@Time,@PriceRate,@Specifications)";
var args = new Dictionary<string, object>
{
{"@No1", info.No1},
{"@No2", info.No2},
{"@Name", info.Name},
{"@Description", info.Description},
{"@WorkersCategory", info.WorkersCategory},
{"@Time", info.Time},
{"@PriceRate", info.PriceRate},
{"@Specifications", info.Specifications},
};
return ExecuteWrite(query, args);
MessageBox.Show("Data Saved Successfully.");
}
catch (Exception ex)
{
throw ex;
}
finally
{
}
}
internal static int UpdateInfo(Info info)
{
try
{
const string query = "UPDATE MyData SET No1 = @No1, No2 = @No2, Name=@Name, Description=@Description, WorkersCategory=@WorkersCategory , WorkersCategory=@WorkersCategory,Time=@Time,PriceRate=@PriceRate,Specifications=@SpecificationsWHERE Id = @Id";
var args = new Dictionary<string, object>
{
{"@Id", info.Id},
{"@No1", info.No1},
{"@No2", info.No2},
{"@Name", info.Name},
{"@Description", info.Description},
{"@WorkersCategory", info.WorkersCategory},
{"@Time", info.Time},
{"@PriceRate", info.PriceRate},
{"@Specifications", info.Specifications},
};
return ExecuteWrite(query, args);
MessageBox.Show("Data Updated Successfully.");
}
catch (Exception ex)
{
throw ex;
}
finally
{
}
}
internal static int DeleteInfo(Info info)
{
try
{
const string query = "Delete from MyData WHERE Id = @id";
var args = new Dictionary<string, object>
{
{"@id", info.Id}
};
return ExecuteWrite(query, args);
MessageBox.Show("Data Deleted Successfully.");
}
catch (Exception ex)
{
throw ex;
}
finally
{
}
}
private static int ExecuteWrite(string query, Dictionary<string, object> args)
{
int numberOfRowsAffected;
using (var con = new SQLiteConnection("Data Source=MyDatabase.sqlite"))
{
con.Open();
using (var cmd = new SQLiteCommand(query, con))
{
foreach (var pair in args)
{
cmd.Parameters.AddWithValue(pair.Key, pair.Value);
}
numberOfRowsAffected = cmd.ExecuteNonQuery();
}
return numberOfRowsAffected;
}
}
}
public class PersonnelBusinessObject
{
internal EventHandler InfoChanged;
List<Info> Info { get; set; }
public PersonnelBusinessObject()
{
Info = DatabaseLayer.GetInfoFromDatabase();
}
public List<Info> GetInfos()
{
return Info = DatabaseLayer.GetInfoFromDatabase();
}
public void AddInfo(Info info)
{
DatabaseLayer.InsertInfo(info);
OnInfoChanged();
}
public void UpdateInfo(Info info)
{
DatabaseLayer.UpdateInfo(info);
OnInfoChanged();
}
public void DeleteInfo(Info info)
{
DatabaseLayer.DeleteInfo(info);
OnInfoChanged();
}
void OnInfoChanged()
{
if (InfoChanged != null)
InfoChanged(this, null);
}
}
public class Info : ViewModelBase
{
private int id;
private string no1;
private string no2;
private string name;
private string description;
// private ObservableCollection<Equi> equipment;
private string workersCategory;
private string time;
private string priceRate;
private string specifications;
public int Id
{
get { return id; }
set
{
id = value;
OnPropertyChanged("Id");
}
}
public string No1
{
get { return no1; }
set
{
no1= value;
OnPropertyChanged("No1");
}
}
public string No2
{
get { return no2; }
set
{
no2 = value;
OnPropertyChanged("No2");
}
}
public string Name
{
get { return name; }
set
{
name = value;
OnPropertyChanged("Name");
}
}
public string Description
{
get { return description; }
set
{
description = value;
OnPropertyChanged("Description");
}
}
public string WorkersCategory
{
get { return workersCategory; }
set
{
workersCategory = value;
OnPropertyChanged("WorkersCategory");
}
}
public string Time
{
get { return time; }
set
{
time = value;
OnPropertyChanged("Time");
}
}
public string PriceRate
{
get { return priceRate; }
set
{
priceRate = value;
OnPropertyChanged("PriceRate");
}
}
public string Specifications
{
get { return specifications; }
set
{
specifications = value;
OnPropertyChanged("Specifications");
}
}
}
public class RelayCommand : ICommand
{
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
public RelayCommand(Action<object> execute)
: this(execute, null)
{
}
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute(parameter);
}
}
public class SelectedItemToItemsSource : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value == null) return null;
return new List<object>() { value };
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
public class ViewModelBase : INotifyPropertyChanged
{
internal void OnPropertyChanged(string prop)
{
if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(prop)); }
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class DataGridBehavior
{
public static DependencyProperty DisplayRowNumberProperty =
DependencyProperty.RegisterAttached("DisplayRowNumber",
typeof(bool),
typeof(DataGridBehavior),
new FrameworkPropertyMetadata(false, OnDisplayRowNumberChanged));
public static bool GetDisplayRowNumber(DependencyObject target)
{
return (bool)target.GetValue(DisplayRowNumberProperty);
}
public static void SetDisplayRowNumber(DependencyObject target, bool value)
{
target.SetValue(DisplayRowNumberProperty, value);
}
private static void OnDisplayRowNumberChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
{
DataGrid dataGrid = target as DataGrid;
if ((bool)e.NewValue == true)
{
EventHandler<DataGridRowEventArgs> loadedRowHandler = null;
loadedRowHandler = (object sender, DataGridRowEventArgs ea) =>
{
if (GetDisplayRowNumber(dataGrid) == false)
{
dataGrid.LoadingRow -= loadedRowHandler;
return;
}
ea.Row.Header = ea.Row.GetIndex();
};
dataGrid.LoadingRow += loadedRowHandler;
ItemsChangedEventHandler itemsChangedHandler = null;
itemsChangedHandler = (object sender, ItemsChangedEventArgs ea) =>
{
if (GetDisplayRowNumber(dataGrid) == false)
{
dataGrid.ItemContainerGenerator.ItemsChanged -= itemsChangedHandler;
return;
}
GetVisualChildCollection<DataGridRow>(dataGrid).
ForEach(d => d.Header = d.GetIndex());
};
dataGrid.ItemContainerGenerator.ItemsChanged += itemsChangedHandler;
}
}
private static List<T> GetVisualChildCollection<T>(object parent) where T : Visual
{
List<T> visualCollection = new List<T>();
GetVisualChildCollection(parent as DependencyObject, visualCollection);
return visualCollection;
}
private static void GetVisualChildCollection<T>(DependencyObject parent, List<T> visualCollection) where T : Visual
{
int count = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < count; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, i);
if (child is T)
{
visualCollection.Add(child as T);
}
if (child != null)
{
GetVisualChildCollection(child, visualCollection);
}
}
}
}
}
The result:
If the response is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentationto enable e-mail notifications if you want to receive the related email notification for this thread.