Hi! Everyone
I have been searching and integrating all checkbox multiselect from the answers I found online, and I l learnt so much, whether they use MVVM Light tollkit and Non-MVVM approach. All of them runs in different way but all are fulfilled the select all requirement that I needed.
The issue I am encountering raises when I use to integrate my DataGrid Loader (LoadDGV) after doing it in Hardcore data
Here are my snippets for select all that runs correctly
using GalaSoft.MvvmLight.Command;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace chkSelectAll
{
public class MainWindowViewModel : INotifyPropertyChanged
{
private List<Item> _items;
public List<Item> Items
{
get { return _items; }
set
{
_items = value;
OnPropertyChanged();
}
}
private bool? isAllSelected;
public bool? IsAllSelected
{
get { return isAllSelected; }
set
{
//Console.WriteLine($"Item IsChecked set to: {value}");
isAllSelected = value;
OnPropertyChanged();
}
}
public RelayCommand chkSelectAll { get; private set; }
public RelayCommand chkSelectCell { get; private set; }
public MainWindowViewModel()
{
chkSelectAll = new RelayCommand(() => chkSelectAllCommand());
chkSelectCell = new RelayCommand(() => chkSelectCellCommand());
Items = GetItems();
IsAllSelected = false;
}
private void chkSelectAllCommand()
{
if (IsAllSelected == true)
Items.ForEach(x => x.IsChecked = true);
else
Items.ForEach(x => x.IsChecked = false);
}
private void chkSelectCellCommand()
{
bool anyUnchecked = Items.Any(x => x.IsChecked == false);
if (Items.All(x => x.IsChecked))
IsAllSelected = true;
else if (Items.All(x => !x.IsChecked))
IsAllSelected = false;
else if (Items.Any(x => x.IsChecked == anyUnchecked))
IsAllSelected = null;
}
private List<Item> GetItems()
{
return new List<Item>
{
new Item { ItemID = 1, ItemName = "Lettuce", ItemCode = "1001", ItemGroup = "Group 1", LastPurchaseDate = "2024-04-21", OnHand = "15.00" },
new Item { ItemID = 6, ItemName = "Chicken", ItemCode = "1006", ItemGroup = "Group 2", LastPurchaseDate = "2024-04-23", OnHand = "40.00" },
new Item { ItemID = 9, ItemName = "Shrimp", ItemCode = "1009", ItemGroup = "Group 3", LastPurchaseDate = "2024-04-23", OnHand = "55.00" }
};
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class Item : INotifyPropertyChanged
{
private bool _isChecked;
public bool IsChecked
{
get { return _isChecked; }
set
{
_isChecked = value;
OnPropertyChanged();
}
}
public int ItemID { get; set; }
public string ItemName { get; set; }
public string ItemCode { get; set; }
public string ItemGroup { get; set; }
public string LastPurchaseDate { get; set; }
public string OnHand { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Here's MainWindow.xaml:
<ResourceDictionary>
<vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" xmlns:vm="clr-namespace:chkSelectAll.ViewModel" />
</ResourceDictionary>
<Window x:Class="chkSelectAll.MainWindow"
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:chkSelectAll"
mc:Ignorable="d"
DataContext="{Binding Source={StaticResource Locator}, Path=MainWindow}"
Title="MainWindow" Height="450" Width="800">
<Grid>
<DataGrid Name="DGV" ItemsSource="{Binding Items}" AutoGenerateColumns="False" CanUserAddRows="False" SelectionChanged="DGV_SelectionChanged">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.HeaderTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding DataContext.IsAllSelected, RelativeSource={RelativeSource AncestorType=DataGrid}, Mode=TwoWay}"
Command="{Binding DataContext.chkSelectAll, RelativeSource={RelativeSource AncestorType=DataGrid}}" />
</DataTemplate>
</DataGridTemplateColumn.HeaderTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsChecked, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
Command="{Binding DataContext.chkSelectCell, RelativeSource={RelativeSource AncestorType=DataGrid}}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Item Name" Binding="{Binding Path=ItemName}" IsReadOnly="True" />
<DataGridTextColumn Header="Item Code" Binding="{Binding Path=ItemCode}" IsReadOnly="True" CanUserSort="False"/>
<DataGridTextColumn Header="Item Group" Binding="{Binding Path=ItemGroup}" IsReadOnly="True" />
<DataGridTextColumn Header="Last Purchase Date" Binding="{Binding Path=LastPurchaseDate}" IsReadOnly="True" />
<DataGridTextColumn Header="On Hand" Binding="{Binding Path=OnHand}" IsReadOnly="True" />
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
Here using HardCore Data:
Here's my integration of LoadDGV inside the MainWindow:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
LoadDGV(null, null);
}
#region LoadDGV
public void LoadDGV(object sender, RoutedEventArgs e)
{
//OdbcConnection conn = null;
OdbcCommand cmd;
string sql = @"SELECT
items.ItemID,
items.ItemName,
CONCAT(itemprefixes.Prefix, items.ItemCodeNumber) AS ItemCode,
itemgroups.GroupName AS ItemGroup,
DATE_FORMAT(items.LastPurchaseDate, '%d %M %Y') AS LastPurchaseDate,
CONCAT(units.UnitName, ' ', TRIM(TRAILING '.' FROM TRIM(TRAILING '0' FROM ROUND(items.OnHand, 1)))) AS OnHand
FROM
items
INNER JOIN
itemgroups ON items.ItemGroupID = itemgroups.GroupID
INNER JOIN
units ON items.UnitID = units.UnitID
INNER JOIN
itemprefixes ON items.PrefixID = itemprefixes.PrefixID
WHERE
items.IsActive = 1";
OdbcDataAdapter da = new OdbcDataAdapter();
//DataTable dt = new DataTable();
DataSet ds = new DataSet();
DataTable dt = new DataTable();
try
{
ModConn.dbConnect();
cmd = new OdbcCommand(sql, ModConn.conn);
da.SelectCommand = cmd;
da.Fill(ds, "Items");
dt = ds.Tables["Items"];
ds.Tables["Items"].DefaultView.Sort = "ItemID";
ds.Tables["Items"].DefaultView.Table.Columns["ItemID"].ColumnMapping = MappingType.Hidden;
#region Items
List<Item> items = new List<Item>();
foreach (DataRow row in dt.Rows)
{
Item item = new Item
{
ItemID = Convert.ToInt32(row["ItemID"]),
ItemName = row["ItemName"].ToString(),
ItemCode = row["ItemCode"].ToString(),
ItemGroup = row["ItemGroup"].ToString(),
LastPurchaseDate = row["LastPurchaseDate"].ToString(),
OnHand = row["OnHand"].ToString()
};
items.Add(item);
}
#endregion
DGV.ItemsSource = ds.Tables["Items"].DefaultView;
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message, "DB Connection Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
finally
{
if (ModConn.conn != null && ModConn.conn.State == ConnectionState.Open)
{
ModConn.conn.Close(); // Close the connection in the finally block
ModConn.conn.Dispose();
//GC.Collect;
}
}
}
#endregion
}
ModConn Class:
using System.Data;
using System.Configuration;
namespace CRUD_InventoryManagement
{
public static class ModConn
{
public static OdbcConnection conn;
public static void dbConnect()
{
try
{
string connectionString = ConfigurationManager.ConnectionStrings["MyDSN"].ConnectionString;
conn = new OdbcConnection(connectionString);
if (conn.State == ConnectionState.Closed)
{
conn.Open();
}
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
}
}
}
Here using Data Binding:
Like what I said, the problem rises when I integrate my LoadDGV to populate from the database
NOTE: I am using SQL Yog IDE and ODBC Data Source Name for database manipulation and connection