-1

I have a simple demo application which shows a list and edit box shows the selected property. If I change the property in edit boxes, the list gets updated. But if I modify the same in code (cmmand handler) it doesn't get updated. Why is that?

<StackPanel>
        <ListView  Margin="10" Name="myListView" ItemsSource="{Binding Persons}" SelectedItem="{Binding SelectedPerson, Mode=TwoWay}">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="First Name" Width="200" DisplayMemberBinding="{Binding FirstName}" />
                    <GridViewColumn Header="Last Name" Width="200" DisplayMemberBinding="{Binding LastName}" />
                </GridView>
            </ListView.View>
        </ListView>
        <TextBox Text="{Binding SelectedPerson.FirstName, UpdateSourceTrigger=PropertyChanged}"/>
        <Button Content="Update" Command="{Binding CmdUpdate}"/>
    </StackPanel>

My ViewModel class is here

   class SimpleListViewModel : Notifier
    {
        private ObservableCollection<Person> _persons;
        public ObservableCollection<Person> Persons
        {
            get
            {
                return _persons;
            }
            set
            {
                _persons = value; // 
                OnPropertyChanged("Persons");
            }
        }

        private Person _selectedPerson;

        public Person SelectedPerson
        {
            get { return _selectedPerson; }
            set 
            { 
                _selectedPerson = value;
                OnPropertyChanged("SelectedPerson");
            }
        }


        public RelayCommand CmdUpdate { get; private set; }

        public SimpleListViewModel()
        {
            var albert = new Person() { FirstName = "Albert", LastName = "Einstein" };
            var bruno = new Person() { FirstName = "Bruno", LastName = "Latour" };
            var charles = new Person() { FirstName = "Charles", LastName = "Darwin" };
            var newton = new Person() { FirstName = "Isaac", LastName = "Newton" };
            var hawking = new Person() { FirstName = "Stephen", LastName = "Hawking" };

            _persons = new ObservableCollection<Person>() { albert, bruno, charles, newton, hawking };

            CmdUpdate = new RelayCommand(OnCmdUpdate, IsCmdUpdateEnabled);
        }

        private bool IsCmdUpdateEnabled(object obj)
        {
            return true;
        }

        private void OnCmdUpdate(object obj)
        {
            //MessageBox.Show(SelectedPerson.FirstName);
            SelectedPerson.FirstName += " CHANGED"; // listview NOT getting updated
        }
    }; 
zar
  • 11,361
  • 14
  • 96
  • 178
  • 1
    Probably because you didn't implemented INotifyPropertyChanged for FirstName and LastName. – Cfun May 31 '20 at 15:36
  • @cfun that’s right but why does the binding with textbox work and it does update the list when FirstName is changed! – zar May 31 '20 at 17:17
  • 1
    Searched it for you: https://stackoverflow.com/q/7767218/1136211 – Clemens May 31 '20 at 19:20

1 Answers1

1

The answer is that when the data is updated via data binding and the Binding.Source is not a DependencyProperty, the binding engine will use reflection to to resolve the source property and then create a ValueChanged handler in case the Binding.Source doesn't implement INotifyPropertyChanged (which seems to be the true for Person). This will create a static reference to the source object, which is known to be a potential memory leak. The TextBox.Text property does all the work, since it is a DependencyProperty (remember that the Binding.Target must be a DependencyProperty). But if you omit the binding engine and manipulate the property directly and the class of this property doesn't implement INotifyPropertyChanged and doesn't raise the PropertyChanged event, the bindings that reference this manipulated property won't get notified about the manipulation.

To solve this Person must implement INotifyPropertyChanged and the Person.FirstName property must raise the INotifyPropertyChanged.PropertyChnaged event.

It is highly recommended to implement properties of every DependencyObject that are either Binding.Source or Binding.Target as DependencyProperty. This will result in the best performance.
If the Binding.Source is not a DependencyObject, it must implement INotifyPropertyChanged. If it doesn't, the performance impact will be significantly worse. See Microsoft Docs: Optimizing Performance: Data Binding.

BionicCode
  • 1
  • 4
  • 28
  • 44