如果更改过滤器,则更新ReadOnlyObservableCollection

问题描述 投票:0回答:1

我通过过滤SourceList派生ReadOnlyObservable集合。过滤器取决于一些不可观察的变量。更改过滤器中的值时,如何确保集合被更新?

using System;
using System.Collections.ObjectModel;
using DynamicData;

namespace ReadOnlyTest
{
    class DemoClass
    {
        public int Id;
        public String Name;
    }

    class Program
    {
          static void Main(string[] args)
        {
            SourceList<DemoClass> SL = new SourceList<DemoClass>();
            ReadOnlyObservableCollection<DemoClass> filtered;

            int filterId = 2;        

            SL.Add(new DemoClass() { Id = 1, Name = "#1" });
            SL.Add(new DemoClass() { Id = 2, Name = "#2" });
            SL.Add(new DemoClass() { Id = 3, Name = "#3" });

            SL.Connect()
                .Filter(entr => { return entr.Id == filterId; })
                .Bind(out ReadOnlyObservableCollection<DemoClass> temp)
                .Subscribe();
            filtered = temp;

            System.Console.WriteLine("filterId = 2");

            foreach (DemoClass dc in filtered)
            {
                System.Console.WriteLine(dc.Name);
            }

            filterId = 3;
            System.Console.WriteLine("filterId = 3");
            foreach (DemoClass dc in filtered)
            {
                System.Console.WriteLine(dc.Name);
            }

            System.Console.ReadLine();
        }
    }
}

输出为:

filterId = 2
#2
filterId = 3
#2

我知道,这是从哪里来的。显然,不是filterIdIObservable更改不会触发和更新过滤器。

但是我正在寻找解决方案当我更改filterId时,我希望SourceList更新filtered

因此结果将是:

filterId = 2
#2
filterId = 3
#3

更新后。

Appliation:在我的wpf应用程序中,过滤器基于MyRowClass SelectedRow,其绑定方式如下:<ComboBox ItemsSource="{Binding AvailableRows}" SelectedItem="{Binding SelectedRow}">。如果更改SelectedRow,我将无法触发刷新ReadOnlyObservableCollection的方法。

c# dynamic-data
1个回答
0
投票

多种解决方案:

[1)使用ReactiveUI

ReactiveUI是一个考虑了响应式编程和动态数据的自以为是的MVVM框架。因为您已经提到用例是WPF应用程序,所以建议在顶部使用ReactiveUI。由于您为过滤器使用了Viewmodel属性,因此该视图模型应实现INotifyPropertyChanged,它与reactui一起使您可以编写:

var observableFilter = this.WhenAnyValue(viewModel => viewModel.FilterId)
.Select(MakeFilter);

这会从属性IObservable<int>中产生一个FilterId,因此当您的视图更改值时,WPF绑定将更新viewmodel属性,并且observableFilter会产生一个新值。添加方法

private Func<DemoClass,bool> MakeFilter(int id)
{
    return demoClass => demoClass.Id == id;
}

这将在谓词中转换您的值,非常类似于您的原始示例,只不过为可观察对象产生的每个值都重建了过滤器。

然后进入您的源列表管道

    SL.Connect()
      .Filter(observableFilter)
      .Bind(out ReadOnlyObservableCollection<DemoClass> temp)
      .Subscribe();

这次,您的过滤器每次更改都会重新应用

** 2)使用主题**

非常类似于先前的解决方案,但是如果您不想使用,则不使用reactui。此方法将使用Subject<T>作为您的过滤器可观察到的源。

在您的viewmodel类中,您将编写这样的属性

private Subject<int> idChanged = new Subject<int>();
private int _filterId;
public FilterId 
{ 
    get => _filterId; 
    set 
    {
        _filterId = value; 
        idChanged.OnNext(value);
    } 
}

Subject<int>是IObservable的对象,其方法OnNext(int value)将使其产生值。然后,该主题的使用方式与第一种解决方案几乎相同:

var observableFilter = idChanged
.Select(MakeFilter);

最后一点是唯一的区别。

我建议您使用第一个解决方案,并学习reactui框架,因为它是负责维护DynamicData的框架

© www.soinside.com 2019 - 2024. All rights reserved.