【问题标题】:Binding to ComboBox using ReactiveUI and Windows Forms使用 ReactiveUI 和 Windows 窗体绑定到 ComboBox
【发布时间】:2015-12-17 14:01:05
【问题描述】:

我想使用 ReactiveUI 将我的视图模型中的属性绑定到 Windows 窗体应用程序中的 ComboBox。

我找到了几个使用 WPF 的示例,但没有使用 Windows 窗体的示例。

编辑: 第 1 部分:将所选值绑定到 以下来自评论的示例:

this.Bind(ViewModel, vm => vm.ViewModelProperty, v => v.comboBox.SelectedValue, comboBox.Events().SelectedValueChanged);

我收到错误:CS1955 Non-invocable member 'Component.Events' cannot be used like a method.

第 2 部分:将 ComboBox 中的项目绑定到视图模型中的集合 ?不知道怎么办

【问题讨论】:

    标签: winforms mvvm binding reactiveui


    【解决方案1】:

    首先,你的视图应该实现IViewFor<YourViewModel>接口,然后

    this.Bind(ViewModel, vm => vm.PropertyToBind, x => comboBox.SelectedValue, comboBox.Events().SelectedValueChanged) 
    

    编辑: 我已经创建了一个演示项目:

    using System;
    using System.Reactive.Linq;
    using System.Windows.Forms;
    using ReactiveUI;
    
    namespace WindowsFormsApplication
    {
        public partial class Form1 : Form, IViewFor<MyViewModel>
        {
            public Form1()
            {
                InitializeComponent();
    
                ViewModel = new MyViewModel();
                comboBox1.DataSource = ViewModel.Items;
    
                var selectionChanged = Observable.FromEvent<EventHandler, EventArgs>(
                    h => (_, e) => h(e),
                    ev => comboBox1.SelectedIndexChanged += ev,
                    ev => comboBox1.SelectedIndexChanged += ev);
                this.Bind(ViewModel, vm => vm.SelectedItem, x => x.comboBox1.SelectedItem, selectionChanged);
            }
    
            public MyViewModel ViewModel { get; set; }
    
            object IViewFor.ViewModel
            {
                get { return ViewModel; }
                set { ViewModel = (MyViewModel)value; }
            }
        }
    
        public class MyItem
        {
            private readonly string _text;
    
            public MyItem(string text)
            {
                _text = text;
            }
    
            public override string ToString()
            {
                return _text;
            }
        }
    
        public class MyViewModel : ReactiveObject
        {
            private MyItem _selectedItem;
    
            public MyViewModel()
            {
                Items = new ReactiveList<MyItem> {new MyItem("test1"), new MyItem("test2")};
            }
    
            public MyItem SelectedItem
            {
                get { return _selectedItem; }
                set { this.RaiseAndSetIfChanged(ref _selectedItem, value); }
            }
    
            public ReactiveList<MyItem> Items { get; private set; }
        }
    }
    

    【讨论】:

    • 谢谢伙计。当我尝试这样做时出现错误......我错过了什么? (见更新的问题)
    • Install-Package reactiveui-events-winforms ;)
    • 再次感谢,但这个包似乎不是 ReactiveUI 的一部分...我只能使用由核心团队维护的包。知道如何使用核心团队发布的包来做到这一点吗?
    • 如果不想使用reactiveui-events-winforms包,可以将comboBox.Events().SelectedValueChanged替换成Observable.FromEvent&lt;EventHandler, EventArgs&gt;( ev =&gt; comboBox.SelectedValueChanged += ev, ev =&gt; comboBox.SelectedValueChanged += ev);
    • +1 谢谢。这似乎在我更改选择(绑定发生)时起作用,但是当应用程序启动时绑定不会发生并且组合框为空(而不是选择第一项)。有什么想法吗?
    【解决方案2】:

    您可以使用Observable.FromEventPattern 方法将SelectedIndexChanged 事件的触发绑定到您的视图模型属性。

    comboBoxWithItems.DataSource = ViewModel.ListOfPossibleItemsProperty;
    comboBoxWithItems.DisplayMember = "Name";
    
    Observable.FromEventPattern<EventHandler, EventArgs>(
        ev => comboBoxWithItems.SelectedIndexChanged += ev,
        ev => comboBoxWithItems.SelectedIndexChanged -= ev)
        .Select(x => comboBoxWithItems.SelectedItem)
        .BindTo(this, x => x.ViewModel.SelectedItemProperty);
    

    【讨论】:

      【解决方案3】:

      您的初始 vm.SelectedItem 为空,并且尚未从视图中更新虚拟机。 在 VM 构造函数中设置初始选择。

      【讨论】:

        【解决方案4】:

        关于值列表的一些改进想法:

        1. comboBox1.DataSource = ViewModel.Items; 的直接集合替换为绑定OneWayBind(ViewModel, vm =&gt; vm.Items, v =&gt; v.comboBox1.DataSource);,这样ViewModel 就不必存在于视图构造函数中,并且ViewModel 可以动态更改。
        2. 使用 ReactiveBindingList 而不是 ReactiveList,以便 WinForms 绑定可以对值列表中的更改做出反应(尽管我还没有针对这种确切情况尝试过)。

        【讨论】:

          【解决方案5】:

          由于其他解决方案在 UWP 应用程序中对我不起作用,因此有一种适用于 WinForms、WPF 和 UWP 应用程序的正确方法:在视图的构造函数中使用 Bind 方法。 WPF/UWP 示例:

          using ReactiveUI;
          using System.Reactive.Disposables;
          
              public sealed partial class MyView : Page, IViewFor<MyViewModel>
              {
          
                  public MyView()
                  {
                      InitializeComponent();
          
                      this.WhenActivated(d =>
                      {
                          this.OneWayBind(ViewModel, vm => vm.Items, v => v.DropDownControl.ItemsSource)
                              .DisposeWith(d);
          
                          this.Bind(ViewModel, vm => vm.SelectedItem, v => v.DropDownControl.SelectedItem)
                              .DisposeWith(d);
                      });
                  }
          
          
                  public MyViewModel ViewModel
                  {
                      get => DataContext as MyViewModel;
                      set => DataContext = value;
                  }
          
                  object IViewFor.ViewModel
                  {
                      get => ViewModel;
                      set => ViewModel = value as MyViewModel;
                  }
              }
          

          在 ViewModel 中:

          using ReactiveUI.Fody.Helpers;
          
              public sealed class MyViewModel : ReactiveObject
              {
                  public void MyViewModel()
                  {
                      // Todo: Load items
                  }
          
                  [Reactive] public IList<MyItem> Items { get; set; } = new List<MyItem>();
                  [Reactive] public MyItem? SelectedItem { get; set; }
              }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-01-10
            • 1970-01-01
            • 1970-01-01
            • 2019-09-27
            • 2015-01-29
            • 1970-01-01
            • 2014-06-09
            相关资源
            最近更新 更多