使用ReactiveUI从ReactiveList获取选定项集合

3

我在wpf中将一个ReactiveList Orders绑定到了datagrid上。 通过以下语法,我成功地获取了单个选定的订单

private Order _selectedOrder;
public Order SelectedOrder
{
    get { return _selectedOrder; }
    set { this.RaiseAndSetIfChanged(ref _selectedOrder, value); }
}
this.WhenAnyValue(x => x.Orders.ItemChanged).Select(x => _selectedOrder = ((Order)x));

但是如果我在数据表格中选择了多个订单,如何获取所选项目?

3个回答

6

首先,您需要将EventPattern转换为IObservable。 您可以使用以下方式完成此操作:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
using System.Windows.Controls;

namespace System.Windows.Controls.Extensions
{
    public static class ListBoxExtensions
    {
        public static IObservable<List<T>> SelectionChanged<T>(this ListBox listBox)
        {
            return Observable.FromEventPattern<SelectionChangedEventHandler, SelectionChangedEventArgs>(
                eh => listBox.SelectionChanged += eh,
                eh => listBox.SelectionChanged -= eh)
                .Select(_ => listBox.SelectedItems.Cast<T>().ToList());
        }
    }
}

然后在您的控件中,将结果绑定到ViewModel,如下所示:

    public partial class MyControl : UserControl, IViewFor<MyViewModel>
    {
        public MyControl()
        {
            InitializeComponent();

            this.WhenActivated(d =>
            {
                MyListView.SelectionChanged<MyItemViewModel>()
                    .Do(list => ViewModel.SelectedItems = list)
                    .SubscribeOn(RxApp.MainThreadScheduler)
                    .ObserveOn(RxApp.MainThreadScheduler)
                    .Subscribe()
                    .DisposeWith(d);
            });
        }

        object IViewFor.ViewModel
        {
            get => ViewModel;
            set => ViewModel = value as MyViewModel;
        }

        public MyViewModel ViewModel
        {
            get => DataContext as MyViewModel;
            set => DataContext = value;
        }
    }

1
它对我有效,谢谢!但是ReactiveUI.Events.WPF怎么可能没有ListBox.SelectionChanged事件呢? - Dmitriy Kudinov
@Evl-ntnt 你有 ReactiveUI.Events.dll 的参考资料吗? 尝试这个链接并告诉我是否有效:https://reactiveui.net/docs/handbook/data-binding/#hack-bindings-and-bindto - navule
@navule 不好意思,ReactiveUI.Events目前还不支持.NET Core。 - MovGP0
1
@movGP0 包已经可用。 - Dmitriy Kudinov

3

您的代码似乎没有实现您想要的功能,因为您似乎正在侦听ReactiveList ItemChanged可观察对象(当数据源更改时将触发),而您想要观察的是网格选择。

尽管未经过测试,但以下代码似乎更符合您想要实现的目标(使用reactiveui-events帮助程序):

// in the VM
public IList<Order> SelectedOrders { /* regular RxUI property as usual */ }

// in the view
this.Grid.Events().SelectionChanged
    .Select(_ => this.Grid.SelectedItems.Cast<Order>().ToList())
    .Subscribe(list => ViewModel.SelectedOrders = list);

我是否理解了您想要实现的目标?

2
你的方法似乎可以解决问题。但是我需要将reactiveUI.events dll添加到项目引用中。即使添加了reactiveui.events.dll,我在datagrid的事件集合中仍然找不到SelectionChanged事件。 - navule

3

根据Gluck提供的提示,我找到了一种通过在视图中为datagrid添加选择更改事件处理程序来获取选定订单集合的方法,以下是具体步骤:

在ViewModel中添加一个响应式属性

private IList<Order> selectedOrders;
public IList<Order> SelectedOrders
{
    get
    {
        return selectedOrders;
    }
    set { this.RaiseAndSetIfChanged(ref selectedOrders, value); }
}

在视图的代码后台

private void OrdersGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    ViewModel.SelectedOrders = OrdersGrid.SelectedItems.Cast<Order>().ToList();
}

1
但是不知道为什么 ReactiveUI.Events.dll 被作为一个单独的程序集从 ReactiveUI 中分离出来。开发人员在识别到这个看起来有用的分离的 dll 时,需要再次向第三方软件批准团队申请授权! - navule

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接