Wpf – Listbox with checkbox not triggering selected item when checkbox is checked/unchecked

listboxmvvmwpf

My application is developed using wpf MVVM pattern where i have a list box which shows a set of operations to be selected with checkbox to check/uncheck. I need to get the selected item whenever a checkbox is checked / unchecked. I am binding the IsChecked property of checkbox to property in my model and selecteditem property of listbox to property in my viewmodel. Whenever i check/uncheck the frist item in the list the selected item event is triggering however the same is not getting triggered when i check/uncheck any item other than the first selected item in the list. I need to capture the changes whenever the user does any changes to listbox items.
Here is my view:

<ListBox Height="280" Width="Auto" ItemsSource="{Binding OperationsInfoCol}" SelectionMode="Multiple"
                        SelectedItem="{Binding Path=SelectedOperationItem,UpdateSourceTrigger=PropertyChanged}" IsEnabled="{Binding CanEnableListBox}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <CheckBox  Content="{Binding OperationName}"
                                              IsChecked="{Binding Path=IsOperationSelected,Mode=TwoWay}" IsEnabled="{Binding Path=CanEnableOperation,Mode=TwoWay}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
    <ListBox.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}">
            <Setter Property="IsSelected" Value="{Binding IsOperationSelected,Mode=TwoWay}"/>
            <Setter Property="IsEnabled" Value="{Binding CanEnableOperation,Mode=TwoWay}"/>
            <Style.Triggers>
                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="Background" Value="Red"/>
                </Trigger>
            </Style.Triggers>

        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

ViewModel:

   public OperationsInfo SelectedOperationItem
    {
        get
        {
            return m_oOperationSelected;
        }
        set
        {
            if (value != null)
            {
                m_oOperationSelected = value;
                OnPropertyChanged("SelectedOperationItem");
                if (null != m_oOperationSelected)
                {
                    ObservableCollection<OperationsInfo> oCol = new ObservableCollection<OperationsInfo>();
                    //if (m_oOperationSelected.CanEnableOperation)
                    {
                        foreach (OperationsInfo itm in OperationsInfoCol)
                        {
                            if (itm.OperationId == m_oOperationSelected.OperationId && m_oOperationSelected.CanEnableOperation)
                            {
                                itm.IsOperationSelected = !m_oOperationSelected.IsOperationSelected;
                            }
                            oCol.Add(itm);
                        }

                        OperationsInfoCol.Clear();
                        OperationsInfoCol = oCol;
                    }
                }
            }
        }
    }

Model:

public class OperationsInfo    { 

    private string m_strOperationName;
    private int m_nOperationId;
    private bool m_bIsOperationSelected;
    private bool m_bCanEnable;
    private LicenseManagerViewModel m_VMLicenseManager; 


public bool IsOperationSelected
    {
        get
        {
            return m_bIsOperationSelected;
        }
        set
        {                
            m_bIsOperationSelected = value;                
            LicenseManagerVM.OperationInfoChecked = value;                
        }
    }

}

Best Answer

Because you set SelectionMode="Multiple", you cannot use SelectedItem.
You also cannot bind to SelectedItems because this property is read-only.

Not all is lost because in your code you bind IsSelected to IsOperationSelected

<ListBox.ItemContainerStyle>
    <Style TargetType="{x:Type ListBoxItem}">
        <Setter Property="IsSelected" 
                Value="{Binding IsOperationSelected,Mode=TwoWay}"/>
    </Style>
</ListBox.ItemContainerStyle>

So now you can process the selected items using IsOperationSelected as indicated in the following example in your ViewModel:

foreach (var operationsInfo in OperationsInfoCol)
{
  if ( operationsInfo.IsOperationSelected)
  {
    // do something...
  }
}
Related Topic