0

I have an Observable collection, but after updating the collecion, my Listview is not updating even after raising Property Changed event see below code:-

Look below XAML:-

 <ListView  Grid.Row="1" Grid.Column="0" Name="lvGroups" Margin="0,34,0,0" 
Grid.RowSpan="2" ItemsSource="{Binding Path=*VideoGroupList*,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
<GridView>
<GridViewColumn Width="150" DisplayMemberBinding="{Binding *Name*}" />
</GridView>

Look below Class

 public class VideoGroupViewModel : ObservableEnitiy
 {
   public ObservableCollection<Group> VideoGroupList { get; set; }
 }

  public abstract class ObservableEnitiy : INotifyPropertyChanged
 {
   public event PropertyChangedEventHandler PropertyChanged;
   protected virtual void OnPropertyChanged(string propertyName)
   {
     this.VerifyPropertyName(propertyName);
      if (this.PropertyChanged != null)
        {
            var e = new PropertyChangedEventArgs(propertyName);
            this.PropertyChanged(this, e);
        }
   }
 }

[Serializable]
public class Group : PropertyChangedNotification
{
    public int ID { get; set; }
    [Required(ErrorMessage = "Group name is required.")]
    public string *Name*
    {
        get { return GetValue(() => Name); ; }
        set
        {
            SetValue(() => Name, value);
        }
    }
    [XmlIgnore]
    public bool IsSelected { get; set; }
}  


     protected T GetValue<T>(Expression<Func<T>> propertySelector)
    {
        string propertyName = GetPropertyName(propertySelector);

        return GetValue<T>(propertyName);
    }

I am calling this way

 VideoGroupList = new ObservableCollection<Group>(videoGroupManager.GetVideoGroups());
 OnPropertyChanged("VideoGroupList");
user3631797
  • 35
  • 1
  • 6
  • Usually this issue is caused by the control refresh event not recognizing the control has changed. The trick that usually works is to add VideoGroupList = null before updating the list. – jdweng Aug 12 '16 at 08:35
  • As a note, setting `Mode=TwoWay` and `UpdateSourceTrigger=PropertyChanged` on the ItemsSource Binding is redundant. It has no effect, because there is no data flow from the target to the source property of the binding. – Clemens Aug 12 '16 at 08:40
  • @jdweng i tried with VideoGroupList = null before updating the list but not working. :( – user3631797 Aug 12 '16 at 08:55
  • Are you sure you are reaching the code? Put break point on code. – jdweng Aug 12 '16 at 09:10
  • @jdweng yes i have tried but no luck – user3631797 Aug 12 '16 at 09:24

2 Answers2

1

Add the following using statements:

using System.Collections.Generic;
using System.Linq;

Change your VideoGroupList line to:

    VideoGroupList.Clear();
    videoGroupManager.GetViewGroups().ToList().ForEach(x => VideoGroupList.Add(x));

This better utilises the change notification built into the ObservableCollection

Gusdor
  • 14,001
  • 2
  • 52
  • 64
benPearce
  • 37,735
  • 14
  • 62
  • 96
0

According to the MSDN Documentation, CollectionChanged will be raised on adding, removing and changing an element in an ObservableCollection. I found this not to be the case however. ObservableCollection.CollectionChanged will only be thrown on add/remove. I use this FullyObservableCollection here instead, with the modification to have T be my ViewModelBase class instead of INotifyPropertyChanged directly.

When I declare my Property then, I use a snippet with the following output: private FullyObservableCollection<Group> _videoGroupList; public FullyObservableCollection<Group> VideoGroupList { get { return _videoGroupList; } set { if(_videoGroupList == value) return; var nil = _videoGroupList == null; _videoGroupList = value; // If null before and not after (declaring it after being null), // call OnPropertyChanged on Change of Collection. if(nil && _videoGroupList != null) _videoGroupList.CollectionChanged += (s,e) => OnPropertyChanged(nameof(VideoGroupList)); OnPropertyChanged(); } } This way you will always have INotifyPropertyChanged Notifications on Add, Remove, Replace and Change action on the collections and every single one of its members. It will save you a lot of hassle since you do not need to reinstanciate the whole collection if one of hundreds of thousands properties in it changes. Remember to initialize it in your constructor though. :)

Community
  • 1
  • 1
Jirajha
  • 483
  • 3
  • 10
  • 1
    This seems like it would raise a lot of potentially unnecessary property change events, your last line, OnPropertyChanged(); will cause the current data context to reevaluate all its bindings, which could be a very expensive operation for a deep or large object graph. You would be better off with an ObservableCollection of ViewModels which implement their own property notification so that property changes are isolated only where needed, e.g http://stackoverflow.com/a/4040810/4490 – benPearce Aug 12 '16 at 10:15
  • @benPearce I noticed the last `OnPropertyChanged();` only gets called when the collection is set completely, not on member change. The `CollectionChanged() => OnPropertyChanged(nameof(MyCollection));` would be what's casuing everything to be refreshed at every change to the collection. If your `ListBox` or `ListView` however uses a `VirtualizingStackPanel` or similar, this is unfortunately neccessary to make changes visualize on `DataTrigger`s or the like in most cases. Smaller Lists with a total of ~200k bindings on ~20k elements is still fine however. Can't tell for more though. – Jirajha Aug 12 '16 at 13:58