首页 > 解决方案 > 反应式 UI 应用多个过滤器

问题描述

我目前正在构建一个 WPF 应用程序(我的第一个应用程序),其中一个视图是一个包含大量列和大量过滤器的 DataGrid。

this.WhenAnyValue我的问题是过滤,我已经设法通过使用和方法让它工作CreateDerivedCollection,但是当我添加越来越多的过滤器时,它们是相互独立的。

我可以看到我的问题是什么,对于每个“过滤器”,我基本上都在覆盖当前的过滤器,但我不确定如何纠正它。

我的想法是我将不得不将所有过滤器放入this.WhenAnyValue方法中,但我注意到这个上限为 12 个属性,而且我还有更多。

这是初始化 ViewModel 和过滤器的代码。

public async Task InitializeAsync()
{
    try
    {
        _mortgageTypes = default(MortgageType)
            .ToDictionary()
            .Select(mt => new ComboBoxMortgageType(mt.Key, mt.Value))
            .ToList();

        using (var db = new MortgageDbContext())
        {
            LenderNames =
                await (from l in db.Lenders
                        select new ComboBoxLenderName(l.Id, l.Name)
                    ).ToListAsync();

            LenderNames.Insert(0, new ComboBoxLenderName(Guid.Empty, "None"));

            _rootList = new ReactiveList<LendersView>(await (from l in db.Lenders
                select new LendersView
                {
                    Citizenship = l.Citizenship.GetDescription(),
                    CriteriaUrl = l.CriteriaUrl,
                    Id = l.Id,
                    FirstTimeBuyer = l.FirstTimeBuyer,
                    MaximumAge = l.MaximumAge,
                    MinimumIncome = l.MinimumIncome,
                    Name = l.Name,
                    NewBuilds = l.NewProperty.AcceptBuyToLet || l.NewProperty.AcceptResidential,
                    PrimaryContact = l.PrimaryContactInformation.ToString(),
                    RatesUrl = l.RatesUrl,
                    SecondaryContact = l.SecondaryContactInformation.ToString(),
                    SelfEmployment = l.SelfEmployment.Accept,
                    SelfEmploymentMinimumIncome = l.SelfEmployment.MinimumIncome,
                    SelfEmploymentYearsBooks = l.SelfEmployment.YearsBooks
                }).ToListAsync());
        }

        this.ObservableForProperty(x => x.SelectedLender)
            .Subscribe(_ => { Lenders = _rootList.CreateDerivedCollection(x => x, x => SelectedLender == Guid.Empty || x.Id == SelectedLender); });

        this.WhenAnyValue(x => x.AcceptSelfEmployment, x => x.SelfEmploymentMinimumIncome, x => x.SelfEmploymentYearsBooks)
            .Subscribe(_ =>
            {
                Lenders = _rootList.CreateDerivedCollection(x => x,
                    x => (!AcceptSelfEmployment || x.SelfEmployment == AcceptSelfEmployment) &&
                        (SelfEmploymentMinimumIncome == default || x.SelfEmploymentMinimumIncome >= SelfEmploymentMinimumIncome) &&
                        (SelfEmploymentYearsBooks == default || x.SelfEmploymentYearsBooks >= SelfEmploymentYearsBooks));
            });
    }
    finally
    {
        IsBusy = false;
    }
}

更新

在 Glenns 的有用回复之后,这是我目前拥有的代码。

public SearchViewModel()
{
    IsBusy = true;
    _rootList = new SourceList<LendersView>();

    var lenderFilter = this.WhenValueChanged(x => x.SelectedLender)
        .Select(LenderNamePredicate);

    var loader =_rootList
        .Connect()               
        .Filter(lenderFilter)
        .ObserveOnDispatcher()
        .Bind(out _lenders)
        .Subscribe();
    Task.Run(InitializeAsync).ContinueWith(res => _rootList.AddRange(res.Result));
    _cleanUp = new CompositeDisposable(loader);
}

private Func<LendersView, bool> LenderNamePredicate(Guid selectedLender)
{
    if (selectedLender == Guid.Empty)
    {
        return lender => true;
    }

    return lender => lender.Id == selectedLender;
}

这似乎工作正常,但是我正在努力使用我在这段代码中的复合过滤器

    this.WhenAnyValue(x => x.AcceptSelfEmployment, x => x.SelfEmploymentMinimumIncome, x => x.SelfEmploymentYearsBooks)
        .Subscribe(_ =>
        {
            Lenders = _rootList.CreateDerivedCollection(x => x,
                x => (!AcceptSelfEmployment || x.SelfEmployment == AcceptSelfEmployment) &&
                    (SelfEmploymentMinimumIncome == default || x.SelfEmploymentMinimumIncome >= SelfEmploymentMinimumIncome) &&
                    (SelfEmploymentYearsBooks == default || x.SelfEmploymentYearsBooks >= SelfEmploymentYearsBooks));
        });

动态数据中有什么等价的吗?另外我真的需要每次都为每个过滤器添加一个单独的函数吗?我只是想我最终将拥有大约 30-40 个过滤器,每个过滤器的功能只会使视图模型更加膨胀。

任何建议表示赞赏!

标签: c#reactiveui

解决方案


推荐阅读