Home > Software design >  Prism Binding to an ObservableCollection with no Setter
Prism Binding to an ObservableCollection with no Setter

Time:06-27

I'm having an issue with a XAML DataGrid which binds to a ObservableCollection. I have 3 classes, A,B,C. The idea is that the ObservableCollection for C will be generated by using Linq to query A and B.

Classes

public class A
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
    public class B
    {
        public int Id { get; set; }
        public int Age { get; set; }
    }
    public class C
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }

DataContext Class

private ObservableCollection<A> _as;
        public ObservableCollection<A> As
        {
            get => _as;
            set { SetProperty(ref _as, value); }
        }

        private ObservableCollection<B> _bs;
        public ObservableCollection<B> Bs
        {
            get => _bs;
            set { SetProperty(ref _as, value);  }
        }

        public ObservableCollection<C> Cs
        {
            get
            {
                var query = from x in As
                            join y in Bs
                            on x.Id equals y.Id
                            select new C() { Name = x.Name, Age = y.Age };

                return new ObservableCollection<C>(query);
            }
        }

MyView.xaml

<DataGrid ItemsSource="{Binding Cs}" Grid.Row="1"/>

If I update the ObservableCollection "As" by removing an item, I can see via a breakpoint that ObservableCollection "Cs" is also updated to reflect the change, but the Datagrid on the UI stays the same. Any help of pointers here would be great, thanks

CodePudding user response:

You have to RaiseNotifyPropertyChanged when As or Bs change to trigger the update of the binding to Cs:

    private ObservableCollection<A> _as;
    public ObservableCollection<A> As
    {
        get => _as;
        set
        { 
            if (SetProperty(ref _as, value)) 
                RaisePropertyChanged(nameof(Cs));
        }
    }

    private ObservableCollection<B> _bs;
    public ObservableCollection<B> Bs
    {
        get => _bs;
        set 
        { 
            if (SetProperty(ref _as, value))
                RaisePropertyChanged(nameof(Cs));
        }
    }

    public IEnumerable<C> Cs
    {
        get
        {
            var query = from x in As
                        join y in Bs
                        on x.Id equals y.Id
                        select new C() { Name = x.Name, Age = y.Age };

            return query;
        }
    }

Also, you want to RaisePropertyChanged whenever As's or Bs's content changes without the whole collection being replaced, i.e.

    public ObservableCollection<A> As
    {
        get => _as;
        set
        { 
            if (_as != null)
                _as.CollectionChanged -= NotifyCs;
            if (SetProperty(ref _as, value))
                RaisePropertyChanged(nameof(Cs));
            if (_as != null)
                _as.CollectionChanged  = NotifyCs;
        }
    }

    private void NotifyCs( object sender, CollectionChangedEventArgs args ) => RaisePropertyChanged(nameof(Cs));
  • Related