2

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;                
        }
    }

}
1
  • XAML code for the View is missing; only the last three tokens are in the question; can you modify the question with more of the XAML, please? Commented Jan 19, 2011 at 6:08

2 Answers 2

1

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...
  }
}
Sign up to request clarification or add additional context in comments.

Comments

0
  1. You should probably bind IsChecked to the IsSelected property of the container ListBoxItem
  2. That way you can handle the SelectionChanged event of the ListBox and react to any changes. (use e.AddedItems and e.RemovedItems to find out what changes where made.)

Some code example:

     <ListBox ItemsSource="{Binding Data}" SelectionChanged="ListBox_SelectionChanged" SelectionMode="Extended">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <CheckBox Content="{Binding Name}" IsChecked="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem}, Path=IsSelected}"/>            
            </DataTemplate>         
        </ListBox.ItemTemplate>
    </ListBox>

Behind:

    private void ListBox_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
    {
        ListBox lb = sender as ListBox;
        if (e.AddedItems.Count > 0)
        {
            foreach (Employee emp in e.AddedItems.Cast<Employee>()) MessageBox.Show("Added: " + emp.Name);
        }
        if (e.RemovedItems.Count > 0)
        {
            foreach (Employee emp in e.RemovedItems.Cast<Employee>()) MessageBox.Show("Removed: " + emp.Name);
        }
    }

2 Comments

We are following MVVM pattern and i need to handle selectionchanged also using MVVM pattern. The code behinf you suggested follows no MVVM i guess.. am i correct? PLease suggest me some alternative.
The code is pretty much design-pattern-agnostic i would say, just what you do when handling SelectionChanged is up to you and it depends on that if it conforms to MVVM.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.