Winforms 使用ReactiveUI和Windows窗体绑定到ComboBox
我想使用ReactiveUI将viewmodel中的属性绑定到Windows窗体应用程序中的组合框 我发现了几个WPF示例,但没有Windows窗体示例 编辑: 第1部分:将选定值绑定到 以下是评论中的示例:Winforms 使用ReactiveUI和Windows窗体绑定到ComboBox,winforms,mvvm,binding,reactiveui,Winforms,Mvvm,Binding,Reactiveui,我想使用ReactiveUI将viewmodel中的属性绑定到Windows窗体应用程序中的组合框 我发现了几个WPF示例,但没有Windows窗体示例 编辑: 第1部分:将选定值绑定到 以下是评论中的示例: this.Bind(ViewModel, vm => vm.ViewModelProperty, v => v.comboBox.SelectedValue, comboBox.Events().SelectedValueChanged); 我得到错误:CS1955非可开票成
this.Bind(ViewModel, vm => vm.ViewModelProperty, v => v.comboBox.SelectedValue, comboBox.Events().SelectedValueChanged);
我得到错误:CS1955非可开票成员“Component.Events”不能像方法一样使用。
第2部分:将组合框中的项绑定到viewmodel中的集合
? 如果不知道如何做,首先,您的视图应该为接口实现
iviewf,然后
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; }
}
}
使用系统;
使用System.Reactive.Linq;
使用System.Windows.Forms;
使用ReactiveUI;
命名空间Windows窗体应用程序
{
公共部分类Form1:Form,IViewFor
{
公共表格1()
{
初始化组件();
ViewModel=新的MyViewModel();
comboBox1.DataSource=ViewModel.Items;
var selectionChanged=Observable.FromEvent(
h=>(u,e)=>h(e),
ev=>comboBox1.SelectedIndexChanged+=ev,
ev=>comboBox1.SelectedIndexChanged+=ev);
this.Bind(ViewModel,vm=>vm.SelectedItem,x=>x.comboBox1.SelectedItem,selectionChanged);
}
公共MyViewModel视图模型{get;set;}
对象IViewFor.ViewModel
{
获取{return ViewModel;}
设置{ViewModel=(MyViewModel)值;}
}
}
公共类MyItem
{
私有只读字符串\u文本;
公共MyItem(字符串文本)
{
_文本=文本;
}
公共重写字符串ToString()
{
返回文本;
}
}
公共类MyViewModel:反应对象
{
私人MyItem _selectedItem;
公共MyViewModel()
{
Items=newreactivelist{newmyitem(“test1”)、newmyitem(“test2”)};
}
公共MyItem SelectedItem
{
获取{return\u selectedItem;}
设置{this.RaiseAndSetIfChanged(ref _selectedItem,value);}
}
公共反应列表项{get;private set;}
}
}
您可以使用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);
comboBoxWithItems.DataSource=ViewModel.ListOfPossibleItemsProperty;
comboBoxWithItems.DisplayMember=“Name”;
可观察的。从事件模式(
ev=>comboBoxWithItems.SelectedIndexChanged+=ev,
ev=>comboBoxWithItems.SelectedIndexChanged-=ev)
.Select(x=>comboBoxWithItems.SelectedItem)
.BindTo(这个,x=>x.ViewModel.SelectedItemProperty);
您的初始vm.SelectedItem为空,并且尚未从视图中更新vm。
在VM构造函数中设置初始选择。与值列表相关的一些改进意见:
替换comboBox1.DataSource=ViewModel.Items的直接集合代码>带有绑定OneWayBind(ViewModel,vm=>vm.Items,v=>v.comboBox1.DataSource)
这样就不必在视图构造函数中存在ViewModel
,并且可以动态更改ViewModel
使用ReactiveBindingList
而不是ReactiveList
,这样WinForms绑定就可以对值列表中的更改做出反应(尽管我还没有在这种情况下尝试过)
由于其他解决方案在UWP应用程序中不适用于我,因此有一种适合于WinForms、WPF和UWP应用程序的方法:使用视图构造函数中的Bind
方法。WPF/UWP示例:
使用ReactiveUI;
使用系统反应性一次性用品;
公共密封部分类MyView:第页,IViewFor
{
公共MyView()
{
初始化组件();
当激活时(d=>
{
this.OneWayBind(ViewModel,vm=>vm.Items,v=>v.DropDownControl.ItemsSource)
.处置(d);
this.Bind(ViewModel,vm=>vm.SelectedItem,v=>v.DropDownControl.SelectedItem)
.处置(d);
});
}
公共MyViewModel视图模型
{
get=>DataContext作为MyViewModel;
set=>DataContext=value;
}
对象IViewFor.ViewModel
{
get=>ViewModel;
将=>ViewModel=值设置为MyViewModel;
}
}
在ViewModel中:
使用ReactiveUI.Fody.Helpers;
公共密封类MyViewModel:ReactiveObject
{
public void MyViewModel()
{
//Todo:加载项目
}
[Reactive]公共IList项{get;set;}=new List();
[被动]公共MyItem?选择EdItem{get;set;}
}
谢谢你,伙计。当我尝试这样做时,我会出错。。。我错过了什么?(请参阅更新的问题)安装包reactiveui事件winforms
;)再次感谢,但此软件包似乎不是ReactiveUI的一部分。。。我只能使用由核心团队维护的包。您知道如何使用核心团队发布的包实现这一点吗?如果您不想使用reactiveui events winforms包,您可以将comboBox.events().SelectedValueChanged
替换为Observable.FromEvent>(ev=>comboBox.SelectedValueChanged+=ev,ev=>comboBox.SelectedValueChanged+=ev);
+1谢谢。当我更改选择时(绑定发生),这似乎有效,但当应用程序启动时,绑定不会发生,并且组合框为空(而不是选择第一项)。有什么想法吗?