Datagrid multiselect checkbox set checked/un-checked mvvm

Kran2022 406 Reputation points
2023-02-24T08:10:55.2233333+00:00

Hi All: Morning

From my datagrid i have a col visible (string propery) checkbox for True or False, i would like select multiple rows in the datagrid or selct all (ctrl + A ) then from a checkbox set active

(checked = select selected rows)

(unchecked = un-select the selected rows)

I added below to the datagrid resource to allow multi selection:

<DataGrid.Resources>
<Style TargetType="DataGridRow"><Setter Property="IsSelected" Value="{Binding IsSelected}" />
</Style>
</DataGrid.Resources>

Checkbox to set selected rows checked/un-checked:


<CheckBox Width="120" Name="cselectall" Content="Select All" Grid.Column="1" VerticalAlignment="Bottom" Margin="30,0,0,30"
	IsChecked="{Binding IsSelected,UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Right"/>

ViewModel:

private bool _isSelected;
public bool IsSelected
{
	get { return _isSelected; }
	set
	{
		_isSelected = value;
		OnPropertyChanged("SelectedItems");
	}
}

public ObservableCollection<Products> SelectedItems { get; }  = new ObservableCollection<Products>();

What am i missing here because when i slected multiple rows or selected all rows (Ctrl+A), by checking the box Name="cselectall" Content="Select All", its not triggering? thanks for your help

 
 public class Products
    {

        public event PropertyChangedEventHandler PropertyChanged;

        string sysid;
        string mainproduct;
        string name;
        string visible;
        string nameicon;


        public string SysId
        {
            get { return sysid; }
            set { sysid = value; }
        }

        public string Mainproduct
        {
            get { return mainproduct; }
            set { mainproduct = value; }
        }
        public string Name
        {
            get { return name; }
            set { name = value; }
        }


        public string Visible
        {
            get { return visible; }
            set
            {
                visible = value;

            }
        }

                
        public string NameIcon
        {
            get { return nameicon; }
            set { nameicon = value; }
        }

        public PriceDetail PriceDetail { get; set; }

        public List<PriceDetail> Prices { get; set; } = new List<PriceDetail>();

     
}
      
Developer technologies | Windows Presentation Foundation
Developer technologies | C#
Developer technologies | C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
0 comments No comments
{count} votes

Answer accepted by question author
  1. Peter Fleischer (former MVP) 19,341 Reputation points
    2023-02-26T07:24:57.2166667+00:00

    Hi,
    I use your old solution and add attached behavior for using SelectedItems of datagrid:

    <Window x:Class="WpfApp1.Window043"
            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:WpfApp043"
            mc:Ignorable="d"
            Title="Kran2022_230224" Height="450" Width="800">
      <Window.DataContext>
        <local:ProductPriceViewModel/>
      </Window.DataContext>
      <Grid>
        <Grid.RowDefinitions>
          <RowDefinition/>
          <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="2*"/>
          <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <DataGrid x:Name="datagrid" local:ProductPriceViewModel.AttProp="True"
                  ItemsSource="{Binding View}" AutoGenerateColumns="False">
          <DataGrid.Columns>
            <DataGridTextColumn Header="SystemPriceID" Binding="{Binding SysId}" Width="*" IsReadOnly="True"/>
            <DataGridTextColumn Header="MianProduct"   Binding="{Binding Mainproduct}" Width="*" IsReadOnly="True"/>
            <DataGridTextColumn Header="Name"   Binding="{Binding Name}" Width="*" IsReadOnly="True"/>
    
            <DataGridTemplateColumn Header="Visible"  Width="100" >
              <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                  <CheckBox IsChecked="{Binding Visible, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" />
                </DataTemplate>
              </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
    
            <DataGridTemplateColumn Header="Add"  Width="*" IsReadOnly="True">
              <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                  <Button>Add</Button>
                </DataTemplate>
              </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
    
            <DataGridTemplateColumn Header="Remove" Width="*" IsReadOnly="True">
              <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                  <Button>Remove</Button>
                </DataTemplate>
              </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
          </DataGrid.Columns>
        </DataGrid>
        <CheckBox Width="120"  
                  Content="Select All" 
                  Grid.Column="1" 
                  VerticalAlignment="Bottom" Margin="30,0,0,30"
                  IsChecked="{Binding IsSelected,UpdateSourceTrigger=PropertyChanged}" 
                  HorizontalAlignment="Right"/>
        <Button Grid.Row="1" Content="Load" Width="100" Margin="10" HorizontalAlignment="left"
                Command="{Binding Cmd}" CommandParameter="Load"/>
        <Button Grid.Row="1" Content="Clear" Width="100" Margin="10" HorizontalAlignment="Center"
                Command="{Binding Cmd}" CommandParameter="Clear"/>
        <Button Grid.Row="1" Content="Save" Width="100" Margin="10" HorizontalAlignment="Right"
                Command="{Binding Cmd}" CommandParameter="Save"/>
        <Grid Grid.Column="1" DataContext="{Binding ElementName=datagrid, Path=SelectedItem}"
              Margin="0,0,0,50">
          <DataGrid ItemsSource="{Binding Prices}" AutoGenerateColumns="False" Margin="10">
            <DataGrid.Columns>
              <DataGridTextColumn Header="FromQuantity" Binding="{Binding FromQuantity}"/>
              <DataGridTextColumn Header="Price" Binding="{Binding Price}"/>
              <DataGridTextColumn Header="ServiceFee" Binding="{Binding ServiceFee}"/>
            </DataGrid.Columns>
          </DataGrid>
        </Grid>
      </Grid>
    </Window>
    

    and code:

    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Linq;
    using System.Runtime.CompilerServices;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Input;
    using System.Xml;
    using System.Xml.Linq;
    
    namespace WpfApp043
    {
    	class ProductPriceViewModel : INotifyPropertyChanged
    	{
    		// ctor
    		public ProductPriceViewModel() => ProductPriceList = new ObservableCollection<Products>();
    
    		// Path of xml file
    		public string FilePath { get; set; } = @"Window041XML.txt";
    
    		// View member
    		private CollectionViewSource cvs = new CollectionViewSource();
    		public ICollectionView View { get => cvs.View; }
    
    		private ObservableCollection<Products> _productPriceList;
    		private ObservableCollection<Products> ProductPriceList
    		{
    			get => this._productPriceList;
    			set
    			{
    				this._productPriceList = value;
    				cvs.Source = value;
    				OnPropertyChanged(nameof(View));
    			}
    		}
    
    		private bool _isSelected;
    		public bool IsSelected
    		{
    			get { return _isSelected; }
    			set
    			{
    				this._isSelected = value;
    				foreach (Products prod in dataGrid.SelectedItems) prod.Visible = value.ToString();
    			}
    		}
    
    		private DataGrid dataGrid;
    
    		#region attached property
    		public static readonly DependencyProperty AttPropProperty =
    				DependencyProperty.RegisterAttached("AttProp", typeof(bool), typeof(ProductPriceViewModel), new PropertyMetadata(false, OnPropChanged));
    		public static bool GetAttProp(DependencyObject obj) => (bool)obj.GetValue(AttPropProperty);
    		public static void SetAttProp(DependencyObject obj, bool par) => obj.SetValue(AttPropProperty, par);
    		private static void OnPropChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    		{
    			DataGrid dg = d as DataGrid;
    			if (dg == null) return;
    			((ProductPriceViewModel)(dg.DataContext)).dataGrid = dg;
    		}
    		#endregion
    
    		public ObservableCollection<Products> SelectedItems { get; } = new ObservableCollection<Products>();
    
    		// Commands
    		public ICommand Cmd { get => new RelayCommand(executemethod, canexecutemethod); }
    
    		private void executemethod(object obj)
    		{
    			switch (obj.ToString())
    			{
    				case "Save":
    					SaveProductsPriceList();
    					break;
    				case "Clear":
    					ProductPriceList.Clear();
    					break;
    				case "Load":
    					ProductPriceList = GetProductsPriceList();
    					break;
    				default:
    					break;
    			}
    		}
    		private static bool canexecutemethod(object obj) => true;
    
    		private XmlDocument productDoc;
    
    #pragma warning disable CS8601 // Dereference of a possibly null reference.
    #pragma warning disable CS8602 // Dereference of a possibly null reference.
    		private ObservableCollection<Products> GetProductsPriceList() //to read xml file contents 
    		{
    			var products = new ObservableCollection<Products>();
    			productDoc = new XmlDocument();
    			productDoc.Load(FilePath);
    			XElement xe0 = XElement.Parse(productDoc.InnerXml);
    			foreach (var xe1 in xe0.Descendants("Products").Elements())
    			{
    				var p = new Products
    				{
    					SysId = xe1.Attribute("Sys_Oid")?.Value,
    					Mainproduct = xe1.Name.ToString(),
    					Name = xe1.Attribute("Name")?.Value,
    					Visible = xe1.Descendants("ProductVisibility")?.FirstOrDefault().Attribute("Visible")?.Value,
    				};
    				foreach (XElement xe2 in xe1.Descendants("ProductPrice"))
    				{
    					p.Prices.Add(new PriceDetail()
    					{
    						Sys_Oid = xe2.Attribute("Sys_Oid")?.Value,
    						Price = xe2.Attribute("Price")?.Value,
    						FromQuantity = xe2.Attribute("FromQuantity")?.Value,
    						ServiceFee = xe2.Attribute("ServiceFee").Value
    					});
    				}
    				products.Add(p);
    			}
    			return products;
    		}
    
    		private void SaveProductsPriceList() //to save xml fiel contents 
    		{
    			foreach (XmlElement pn in productDoc.SelectNodes("/Data/Products/*"))
    			{
    				Products pp = ProductPriceList.Where(p => p.SysId == pn.GetAttribute("Sys_Oid")?.ToString()).FirstOrDefault();
    				if (pp != null)
    				{
    					foreach (XmlNode visibility in pn.SelectNodes("Visibilities"))
    					{
    						foreach (XmlNode productVisibilty in visibility.SelectNodes("ProductVisibility"))
    						{
    							productVisibilty.Attributes["Visible"].InnerText = pp.Visible;
    							foreach (XmlNode price in productVisibilty.SelectNodes("Prices"))
    							{
    								foreach (XmlNode productPrice in price.SelectNodes("ProductPrice"))
    								{
    									PriceDetail pd = pp.Prices.Where(p => p.Sys_Oid == productPrice.Attributes["Sys_Oid"]?.Value.ToString()).FirstOrDefault();
    									if (pd != null)
    									{
    										productPrice.Attributes["FromQuantity"].InnerText = pd.FromQuantity;
    										productPrice.Attributes["Price"].InnerText = pd.Price;
    										productPrice.Attributes["ServiceFee"].InnerText = pd.ServiceFee;
    									}
    								}
    							}
    
    						}
    					}
    				}
    			}
    			productDoc.Save(FilePath);
    		}
    
    		public static string RenameToCentiMeters(string inches)
    		{
    			var dic = GetInchesToCentimetersPairs();
    			foreach (var pair in dic.OrderByDescending(x => x.Key.Length))
    				inches = inches.Replace(pair.Key, pair.Value);
    			return inches;
    		}
    
    		private static Dictionary<string, string> GetInchesToCentimetersPairs()
    		{
    			var dic = new Dictionary<string, string>();
    			dic.Add("2x4", "5x10");
    			dic.Add("2x4/8", "5x10/20");
    			return dic;
    		}
    
    		// INotifyPropertyChanged
    #pragma warning disable CS8612 // Nullability of reference types in type doesn't match implicitly implemented member.
    		public event PropertyChangedEventHandler PropertyChanged;
    		public void OnPropertyChanged([CallerMemberName] string info = "") =>
    				PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(info));
    	}
    
    	//#pragma warning disable CS8603 // Dereference of a possibly null reference.
    	public class Products : INotifyPropertyChanged
    	{
    		public string SysId { get; set; }
    		public string Mainproduct { get; set; }
    		public string Name { get; set; }
    
    		private string _visible;
    		public string Visible
    		{
    			get => this._visible;
    			set
    			{
    				this._visible = value;
    				OnPropertyChanged();
    			}
    		}
    		public PriceDetail PriceDetail { get; set; }
    		public List<PriceDetail> Prices { get; set; } = new List<PriceDetail>();
    
    		// INotifyPropertyChanged
    #pragma warning disable CS8612 // Nullability of reference types in type doesn't match implicitly implemented member.
    		public event PropertyChangedEventHandler PropertyChanged;
    		public void OnPropertyChanged([CallerMemberName] string info = "") =>
    				PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(info));
    	}
    
    	public class PriceDetail
    	{
    		public string Sys_Oid { get; set; }
    		public string FromQuantity { get; set; }
    		public string Price { get; set; }
    		public string ServiceFee { get; set; }
    	}
    
    #pragma warning disable CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member (possibly because of nullability attributes).
    #pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
    	public class RelayCommand : ICommand
    	{
    		private readonly Predicate<object> _canExecute;
    		private readonly Action<object> _action;
    		public RelayCommand(Action<object> action) { _action = action; _canExecute = null; }
    		public RelayCommand(Action<object> action, Predicate<object> canExecute) { _action = action; _canExecute = canExecute; }
    		public void Execute(object o) => _action(o);
    		public bool CanExecute(object o) => _canExecute == null ? true : _canExecute(o);
    		public event EventHandler CanExecuteChanged
    		{
    			add { CommandManager.RequerySuggested += value; }
    			remove { CommandManager.RequerySuggested -= value; }
    		}
    	}
    }
    
    

    Result:

    x

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.