Search code examples
wpfdata-bindingitemtemplate

WPF update two values when a property is changed


I've run into some difficulty with the following XAML:

<ListBox x:Name="lstRegion" ItemsSource="{Binding}" SelectionMode="Multiple">
    <ListBox.ItemTemplate>
        <DataTemplate DataType="ListBoxItem">
            <CheckBox  Content="{Binding Element.Region_Code}" IsChecked="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected, Mode=TwoWay}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox> 

This code will update the IsSelected property on the containing ListBoxItem, allowing me to return this content from lstRegion.SelectedItems.

But, I also need to update a value in the ItemsSource when the checkbox IsChecked value changes. Is there a way to update the value in the ItemsSource as well as the ListBoxItem? It seems that I can either change one or the other, just not both. I'm sure I can catch the PropertyChanged event and manually update the value, but that seems like I'm doing an extra step because I don't understand something correctly. Any help is appreciated.

Here's the class that's used to populate the ItemsSource on the ListBox:

 public class SelectionItem<T> : INotifyPropertyChanged
    {
        #region private fields
        /// <summary>
        /// indicates if the item is selected
        /// </summary>
        private bool _isSelected;
        #endregion

        public SelectionItem(T element, bool isSelected)
        {
            Element = element;
            IsSelected = isSelected;
        }

        public SelectionItem(T element):this(element,false)
        {

        }

        #region public properties
        /// <summary>
        /// this UI-aware indicates if the element is selected or not
        /// </summary>
        public bool IsSelected
        {
            get
            {
                return _isSelected;
            }
            set
            {
                if (_isSelected != value)
                {
                    _isSelected = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("IsSelected"));
                }
            }
        }

        /// <summary>
        /// the element itself
        /// </summary>
        public T Element { get; set; }
        #endregion

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;
   }

Solution

  • Something like this should give you what you need:

    <ListBox x:Name="lstRegion" ItemsSource="{Binding}" SelectionMode="Multiple">
        <ListBox.ItemTemplate>
            <DataTemplate DataType="ListBoxItem">
                <CheckBox Content="{Binding Element.Region_Code}" IsChecked="{Binding IsSelected, Mode=TwoWay}"/>
            </DataTemplate>
        </ListBox.ItemTemplate>
        <ListBox.ItemContainerStyle>
            <Style TargetType="x:Type ListBoxItem}">
                <Setter Property="IsSelected" Value="{Binding IsSelected}" />
            </Style>
        </ListBox.ItemContainerStyle>
    </ListBox>