Home > Back-end >  WPF - Trigger a change of a field contained in a normal property vs ObservableCollection property
WPF - Trigger a change of a field contained in a normal property vs ObservableCollection property

Time:10-16

In the code example below a different behavior is happening for a property of type Person vs a property of type ObesrvableCollection. In both cases a TextBox is bound to edit the Person.Name field. And for both cases a TextBlock is used to display the updated value on the field. In the case of ObservableCollection, the TextBlock is updated on After an edit has bin done on TextBox, after "faded away from focus" event. In The case of a normal property, the TextBlock is not updated when the value is changed in the TextBox on the faded away from focus. What is the difference? What is happening under the hood in the case of ObservableColletion that the field values gets updated?

Xaml View:

<UserControl ...>
    <StackPanel>
        <ListBox ItemsSource="{Binding People}" Height="100">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBox Text="{Binding Name}"/>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

        <TextBlock Text="{Binding People[0].Name}"/>

        <TextBox Text="{Binding Mike.Name}"/>
        <TextBlock Text="{Binding Mike.Name}"/>
    </StackPanel>
</UserControl>

ViewModel:

class MainViewModel : BindableBase
    {

        private Person _mike;
        public Person Mike
        {
            get { return _mike; }
            set { SetProperty(ref _mike, value); }
        }

        public ObservableCollection<Person> People { get; set; } = new ObservableCollection<Person>();

        public MainViewModel()
        {

            People.Add(new Person("Lisa"));
            People.Add(new Person("Chris"));
            People.Add(new Person("Orlando"));
        }
    }

Person class:

class Person
{
    public string Name { get; set; }

    public Person(string name)
    {
        Name = name;
    }
}

CodePudding user response:

The Person needs to implement BindableBase (assuming that implements INotifyPropertyChanged), and you need to set the Name property like this:

private string _name;
public string Name
{
    get { return _name; }
    set { SetProperty(ref _name, value); }
}

The ObservableCollection purpose is to notify when an item is added, moved or removed; it does not track the properties of an item.

CodePudding user response:

Use INotifyPropertyChanged:

class CarList : INotifyPropertyChanged
    {
       
        public string ModelNumber { get; set; }

        private string modelName;
        public string ModelName
        {
            get { return modelName; }
            set
            {
                modelName = value;
                OnPropertyChanged("ModelName");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged([CallerMemberName] string pchange = "")
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(pchange));
        }
    }
  • Related