winform上视图模型双向绑定 TView 的使用
()#winform上视图模型双向绑定 TView 的使用
TView 其实不是什么神秘的东西,而是上一篇文章 [ c# 模仿 vue 实现 winform 的数据模型双向绑定](http://blog.csdn.net/mengtoumingren/article/details/78680208) 实现的一个组件(我也不知道该不该叫组件)。
在上一篇讲了实现的原理(回过头来看,讲的还是有点乱),这次就详细介绍组件的使用。尽管 使用wpf 开发就可以简单实现绑定,但是在平时的开发,需要窗体的好些还是会选择winform。既然要使用,总要起个名字吧,然后就想到这个名字了(若是"TView"这个名字涉及侵权,麻烦联系一下哦)。好了,下面是详细使用示例。
1. 前期工作
项目用要使用该组件首先需要添加引用,然后在类文件中引用。
using TView;
2. 设计好界面,并建立视图模型
窗口的设计就不用多说了,按需求了。设计完界面,然后根据窗口创建视图模型。
数据模型需要做一些变更:
创建多个订阅者容器
private List<Dep> lsDep = Dep.InitDeps(3);
或者单个订阅者容器
Dep dep = new Dep();
重构模型属性的 get set 方法,如
public int Percent
{
get
{
return lsDep[0].Get<int>();
}
set
{
lsDep[0].Set(value);
}
}
public string Name
{
get
{
return lsDep[1].Get<string>();
}
set
{
lsDep[1].Set(value);
}
}
3. 绑定指令
TView 支持属性和事件的绑定。通过给 控件 的 Tag属性配置指令值。
属性绑定:
data-控件属性名-视图模型的属性 或者缩写 dt-控件属性名-视图模型的属性。如绑定控件的Text属性为模型的Name 属性 dt-Text-Name .
还可以 data-视图模型的属性 或者 dt-视图模型的属性。这种情况下,组件会默认查看控件是否包含以下属性:DataSource Value Text,优先度从左往右,匹配后则不会再往下匹配。
ps:假如某个控件需要绑定多个属性,比如 下拉框ComboBox,希望这个的数据源DataSource为某个数据列表,而选择不同的值SelectedValue/Text绑定到另一个属性,则可以明确绑定的属性而不使用缩略值。
事件绑定:
ev-控件的事件名-模型的方法
例如 按钮的Click 事件 绑定 模型中的 Change方法 ev-Click-Change
ps:绑定方法参数必须为 object,且参数不能多余两个,可不传参,传一个参数是,接收的是 包装了 object sender, EventArgs e 这两个参数。
**不论是事件还是属性的绑定,均支持多绑定,各个属性或者事件之间使用‘|’ 隔开,如 dt-Text-Name|ev-Click-Change**
4. 绑定视图模型到界面
这里一般在窗体初始化时进行数据的绑定。
private void Form1_Load(object sender, EventArgs e)
{
new ViewBind(this, model);
}
ps:这里的this 传的是整个窗体,假如一个窗体中分多个区域,每个区域的数据模型不相关的话,可以通过一个penal 控件将区域的控件包起来,然后传入 penal 。
Demo
这里给一个例子。
界面设计如图:
视图模型如下:
public class ViewModel
{
private Random rand = new Random();
public List<string> Data = new List<string>()
{ "aaaaa", "bbbbbb", "ccccc","ddddd","eeeee" };
//初始化属性存放订阅者的容器
private List<Dep> lsDep = Dep.InitDeps(3);
Dep dep = new Dep();
/// <summary>
/// 构造函数
/// </summary>
public ViewModel()
{
//异步调用,用于测试异步操作
new Action(() =>
{
while (true)
{
Thread.Sleep(3000);
this.Name = "异步调用" + rand.Next(0, 1000);
}
}).BeginInvoke(null, null);
}
public int Percent
{
get
{
return lsDep[0].Get<int>();
}
set
{
lsDep[0].Set(value);
}
}
public string Name
{
get
{
return lsDep[1].Get<string>();
}
set
{
lsDep[1].Set(value);
}
}
public string SelectValue
{
get
{
return lsDep[2].Get<string>();
}
set
{
lsDep[2].Set(value);
}
}
/*
*
* 事件方法允许接收 0/1/2 个参数
*/
/// <summary>
/// 选择事件改变
/// </summary>
/// <param name="s"></param>
/// <param name="e"></param>
public void SelectChange(object s, object e)
{
this.SelectValue = Data[rand.Next(0, 5)];
}
/// <summary>
///
/// </summary>
/// <param name="s"></param>
/// <param name="e"></param>
public void NameChange(object s, object e)
{
this.Name = DateTime.Now.Millisecond.ToString();
}
public void PercentChange(object s, object e)
{
this.Percent = rand.Next(0, 100);
}
}
ps
第一行控件分别绑定的指令:data-Text-SelectValue ,data-SelectValue , data-SelectValue|ev-Click-SelectChange
第二行控件分别绑定的指令:dt-Name ,dt-Name , data-Name|ev-Click-NameChange
第三行控件分别绑定的指令:data-Percent ,data-Percent , data-Percent|ev-Click-PercentChange
第四行进度条控件绑定的指令:data-Percent
第五行滚动条控件绑定的指令:data-Percent
效果
源码链接
上一篇: Jetpack LifeCycle
下一篇: discuz7.2如何防止垃圾贴