Home > OS >  Modifying property in codebehind doesn't update DataContext binding in ItemsTemplate of ListBox
Modifying property in codebehind doesn't update DataContext binding in ItemsTemplate of ListBox

Time:07-04

I made a test project to demonstrate my issue.
In the main window, I define a ListBox and it's ItemTemplate, along with 1 button, Update.
In the DataTemplate I define a CheckBox with IsChecked bound to the IsUsed property.

<Window x:Class="Tests.MainWindow"
        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"
        mc:Ignorable="d">
    <WrapPanel>
        <ListBox x:Name="listBox">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <CheckBox IsChecked="{Binding IsUsed}"/>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <Button Content="Update" Click="ButtonUpdate_Click"/>
    </WrapPanel>
</Window>

Business object for items:

namespace Tests;

public class Foo
{
    public Foo(bool isUsed) => IsUsed = isUsed;

    public bool IsUsed { get; set; }

    public override string ToString() => IsUsed.ToString();
}

Code behind for MainWindow:

using System.Windows;

namespace Tests;

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        listBox.ItemsSource = new Foo[]
        {
            new(true),
            new(false),
        };
    }

    private void ButtonUpdate_Click(object sender, RoutedEventArgs e)
    {
        Foo? SelectedItem = (Foo)listBox.SelectedItem;
        if (SelectedItem is not null)
        {
            SelectedItem.IsUsed = false;
        }
    }
}

The Update button inverts the boolean property IsUsed of the selected item.

Executing the program shows that the first item's checkbox is checked, as it should be.

However, clicking on Update doesn't uncheck the checkbox even though it should, since it sets IsUsed property to false.

I guess I need to modify the binding to fix the problem.

This problem isn't specific to booleans, I tested with other types.

CodePudding user response:

When change any property in behind, you need notify to UI this change for bind know.

 public class Foo : INotifyPropertyChanged
    {
        #region INotifyPropertyChanged implementos
        public event PropertyChangedEventHandler PropertyChanged;
        public void RaisePropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion

        private bool isUsed;
       
        public Foo(bool isUsed) => IsUsed = isUsed;

        public bool IsUsed { get => isUsed; set { isUsed = value; RaisePropertyChanged(); } }

        public override string ToString() => IsUsed.ToString();
    }

and change Checkbox bind to twoway if you need change by UI :)

  <CheckBox IsChecked="{Binding IsUsed, Mode=TwoWay}"/>

sorry about my english :/

  • Related