Wpf CheckedListBox SelectedIndex in an ICommand

BigH61 581 Reputation points
2022-12-14T21:58:25.383+00:00

I hope someone can help.
I am trying to follow MVVM principles and using .Net Core C#
I have a need to utilise a CheckedListBox so I am currently utilising the following simple solution:

<ListBox x:Name="PeopleListBox" Grid.Column="1" ItemsSource="{Binding PeopleCollection}" HorizontalContentAlignment="Stretch">  
                <ListBox.ItemTemplate>  
                <DataTemplate>  
                    <CheckBox x:Name="GridColumnVisibilityCheckBox" Content="{Binding FirstName}" HorizontalAlignment="Stretch" IsChecked="{Binding Path=IsSelected, Mode=TwoWay}"/>  
                </DataTemplate>  
                </ListBox.ItemTemplate>  
                </ListBox>  

I require a Command when ever an item IsSelected/Checked/Unchecked.
The command would need to have access to the SelectedIndex and whether the item was checked.
I appear to be going round in circles on this with no look and would very much appreciate some assistance, sample code for a solution.

Developer technologies Windows Presentation Foundation
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Peter Fleischer (former MVP) 19,341 Reputation points
    2022-12-15T09:09:10.7+00:00

    Hi,
    to solve your problem you must bind Command of CheckBox to ICommand property in ViewModel and CommandParameter to actual item. See my demo:

    <Window x:Class="WpfApp1.Window035"  
            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:WpfApp035"  
            mc:Ignorable="d"  
            Title="BigH61-8942_221215" Height="450" Width="800">  
      <Window.Resources>  
        <local:ViewModel x:Key="vm"/>  
      </Window.Resources>  
      <Grid DataContext="{StaticResource vm}">  
        <Grid.ColumnDefinitions>  
          <ColumnDefinition Width="100"/>  
          <ColumnDefinition/>  
        </Grid.ColumnDefinitions>  
        <Grid.RowDefinitions>  
          <RowDefinition/>  
          <RowDefinition/>  
        </Grid.RowDefinitions>  
        <ListBox Grid.Column="1" ItemsSource="{Binding PeopleCollection}" HorizontalContentAlignment="Stretch">  
          <ListBox.ItemTemplate>  
            <DataTemplate>  
              <CheckBox Content="{Binding FirstName}" HorizontalAlignment="Stretch"   
                        IsChecked="{Binding Path=IsSelected, Mode=TwoWay}"   
                        Command="{Binding Source={StaticResource vm}}" CommandParameter="{Binding}"/>  
            </DataTemplate>  
          </ListBox.ItemTemplate>  
        </ListBox>  
        <StackPanel Grid.Column="1" Grid.Row="1" DataContext="{Binding LastItem}">  
          <Label Content="Last checked / unchecked item"/>  
          <Label Content="  FirstName"/>  
          <TextBlock Text="{Binding FirstName}"/>  
          <Label Content="  IsSelected"/>  
          <TextBlock Text="{Binding IsSelected}"/>  
        </StackPanel>  
      </Grid>  
    </Window>  
    

    and ViewModel:

    Result:

    271001-x.gif


  2. Peter Fleischer (former MVP) 19,341 Reputation points
    2022-12-17T18:42:02.49+00:00

    Hi,
    for resetting change your ViewModel:

    using System;  
    using System.Collections.ObjectModel;  
    using System.ComponentModel;  
    using System.Runtime.CompilerServices;  
    using System.Threading;  
    using System.Threading.Tasks;  
    using System.Windows;  
    using System.Windows.Data;  
    using System.Windows.Input;  
      
    namespace WpfApp035  
    {  
     public class ViewModel : ICommand, INotifyPropertyChanged  
     {  
     private CollectionViewSource cvs = new();  
     public ICollectionView PeopleCollection  
     {  
     get  
     {  
     if (cvs.Source == null) cvs.Source = LoadData();  
     return cvs.View;  
     }  
     }  
      
     public People? LastItem { get; set; }  
      
     public event EventHandler? CanExecuteChanged;  
     public event PropertyChangedEventHandler? PropertyChanged;  
      
    #pragma warning disable CS1998, CS4014, CS8602  
     public bool CanExecute(object? parameter) => true;  
     public async void Execute(object? parameter)  
     {  
     var item = (parameter == null) ? null : (People)parameter;  
     LastItem = item;  
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(LastItem)));  
     Task.Factory.StartNew(() => ResetIsSelected(item));  
     }  
      
     private async void ResetIsSelected(People? p)  
     {  
     if (p == null) return;  
     await Task.Delay(1000);  
     p.IsSelected = false;  
     p.OnPropertyChanged("IsSelected");  
     }  
      
     private ObservableCollection<People> LoadData()  
     {  
     ObservableCollection<People> col = new();  
     for (int i = 1; i < 10; i++) col.Add(new People() { FirstName = $"FirstName {i}" });  
     return col;  
     }  
      
     public class People : INotifyPropertyChanged  
     {  
     public string FirstName { get; set; }  
     public bool IsSelected { get; set; }  
      
     public event PropertyChangedEventHandler? PropertyChanged;  
     internal void OnPropertyChanged([CallerMemberName] string propName = "") =>  
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));  
     }  
     }  
    }  
    

    Result:

    271683-x.gif

    0 comments No comments

Your answer

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