wpf中UserControl的几种绑定方式
我们经常会抽取一些可重用的控件,某个属性是否需要重用,直接决定了这个属性的绑定方式。
1、完全不可重用的控件
有一些与业务强相关的控件,它们的属性完全来自ViewModel,越是相对复杂的控件,越容易这样。比如:
// ChooseUc.xaml
<UserControl>
<StackPanel Orientation="Horizontal">
<Label Content="选择一个水果: "/>
<ComboBox ItemsSource="{Binding Fruits}"/>
</StackPanel>
</UserControl>
使用的时候直接 <my:ChooseUc /> 即可直接绑定到ViewModel里的 List<Fruit> Fruits ,不用做额外的工作。好处是特别方便,代价是与vm完全耦合。
2、完全可重用的控件
类似的控件多了,就能抽出一些完全可重用的控件,这些控件与业务无关。为了实现这种重用性,要做到:
- 抽出所有可变的属性,定义在控件内部
- 绑定控件内定义的这些属性
- 外部使用时,再将这些属性与vm绑定
具体如下:
// ChooseUc.xaml
<UserControl>
<StackPanel x:Name="root" Orientation="Horizontal">
<Label Content="{Binding Header}"/>
<ComboBox ItemsSource="{Binding Items}"/>
</StackPanel>
</UserControl>
相应的cs代码为:
// ChooseUc.xaml.cs
public ChooseUc() {
InitializeComponent();
root.DataContext = this; // 这句很关键!
}
public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register("Items", typeof(IEnumerable), typeof(ChooseUc));
public IEnumerable Items {
get { return (IEnumerable)GetValue(ItemsProperty); }
set { SetValue(ItemsProperty, value); }
}
//HeaderProperty类似,此处省略
使用的时候为:
<my:ChooseUc Header="{Binding FruitHeader}" Items="{Binding Fruits}" />
特别注意 root.DataContext = this; ,这一句把内部的控件与外界隔离了,内部事实上已经看不到ViewModel了,只能看到内部定义的属性(Header、Items之类的)。麻烦一些,但好处是可以适用于1个标签+1个下拉框的任何场景,复用性高。
缺点是,在级联的自定义控件里,简直是个噩梦。设想有3个UserControl:C>B>A (C包含B、B包含A)。只有C有对应的vm,这种情况下B要包含A的所有属性。实际情况是,B要包含所有子控件的所有属性,这无疑是让人郁闷的!
好在多数情况下我们并不需要级联嵌套自定义控件,而且我们也可以放弃一些复用性,以获得默认绑定vm的便利。
3、部分可重用的控件
还有一类情况就是控件部分可重用,考虑这样一个场景:用户可以选择2个水果,这时Fruits可以直接绑到vm里,但SelectedFruit需要分别绑定:
// ChooseUc.xaml
<UserControl x:Name="uc">
<StackPanel Orientation="Horizontal">
<Label Content="选择一个水果: "/>
<ComboBox ItemsSource="{Binding Fruits}" SelectedItem="{Binding SelectedFruit, ElementName=uc}"/>
</StackPanel>
</UserControl>
// 类似的,ChooseUc.xaml.cs里定义SelectedFruit依赖属性
使用的时候为:
<StackPanel>
<my:ChooseUc SelectedFruit="{Binding Fruit1}" />
<my:ChooseUc SelectedFruit="{Binding Fruit2}" />
</StackPanel>
这种情况下,即使是级联,Fruits也不需要重复定义,又获得了SelectedFruit的灵活性。这里的关键是:只把需要复用的属性,绑定到控件内部,其他属性继承vm就好。
4、小结
实际开发的过程中,大部分的情况是1+3,即完全不重用+部分重用的控件。即使遇到完全重用的控件,也不大会形成级联。
wpf中UserControl的几种绑定方式的更多相关文章
- 在WPF中UserControl
在这里我们将将打造一个UserControl(用户控件)来逐步讲解如何在WPF中自定义控件,并将WPF的一些新特性引入到自定义控件中来.我们制作了一个带语音报时功能的钟表控件, 效果如下: 在VS中右 ...
- WPF中的命令与命令绑定(一)
原文:WPF中的命令与命令绑定(一) WPF中的命令与命令绑定(一) 周银辉说到用户输入,可能我们更多地会联想到 ...
- js this详解,事件的三种绑定方式
this,当前触发事件的标签 在绑定事件中的三种用法: a. 直接HTML中的标签里绑定 onclick="fun1()"; b. 先获取Dom对象,然后利用dom对象在js里绑定 ...
- Dom事件的三种绑定方式
1.事件 2. onclick, onblur, onfocus, 需求:请写出一个行为,样式,结构,相分离的页面. JS, CSS, HTML, 示例1,行为结构样式粘到一起的页面: & ...
- 巨蟒python全栈开发数据库前端6:事件onclick的两种绑定方式&&onblur和onfocus事件&&window.onload解释&&小米商城讲解
1.回顾上节内容(JavaScript) 一.JavaScript概述 1.ECMAScript和JavaScript的关系 2.ECMAScript的历史 3.JavaScript是一门前后端都可以 ...
- WPF中的命令与命令绑定(二)
原文:WPF中的命令与命令绑定(二) WPF中的命令与命令绑定(二) 周银辉在WPF中,命令(Commandi ...
- 整理:WPF中Binding的几种写法
原文:整理:WPF中Binding的几种写法 目的:整理WPF中Bind的写法 <!--绑定到DataContext--> <Button Content="{Bindin ...
- JAVA高级架构师基础功:Spring中AOP的两种代理方式:动态代理和CGLIB详解
在spring框架中使用了两种代理方式: 1.JDK自带的动态代理. 2.Spring框架自己提供的CGLIB的方式. 这两种也是Spring框架核心AOP的基础. 在详细讲解上述提到的动态代理和CG ...
- Vue中常用的几种传值方式
Vue中常用的几种传值方式 1. 父传子 父传子的实现方式就是通过props属性,子组件通过props属性接收从父组件传过来的值,而父组件传值的时候使用 v-bind 将子组件中预留的变量名绑定为da ...
随机推荐
- svn提交时强制添加注释
1,找到Repositories 文件夹 2,在Repositories 中找到对应的工程, 3,在工程下找到hooks文件夹 4.在hooks文件夹下添加 :pre-commit.bat文件;文件内 ...
- [转]MySQL5.6新特性之Multi-Range Read
这几天看到mrr的东西,刚好看到以前我们组的一个小伙的博客,我看挺全的,就转过来了,原博客地址请戳 一 介绍 MySQL 5.6版本提供了很多性能优化的特性,其中之一就是 Multi-Range ...
- jQuery全选/反选checkbox
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- udhcpc命令【转】
udhcpc -i usb0 route 转自:http://blog.csdn.net/hshl1214/article/details/8684740 由于要使用网络通讯,所以不可避免的要用到dh ...
- ReactiveCocoa常见操作方法介绍/MVVM架构思想
1.ReactiveCocoa常见操作方法介绍. 1.1 ReactiveCocoa操作须知 所有的信号(RACSignal)都可以进行操作处理,因为所有操作方法都定义在RACStream.h中, ...
- Oracle logmnr工具分析日志脚本
在oracle:对logmnr工具分析日志这个不陌生:对数据恢复应用场景经常用到:这里为了方便对归档日志进行分析: 当然网上有一个logmnr界面的工具:感觉很人性化:下载需要积分:为此写一个脚本. ...
- myisam压缩(前缀压缩)索引
myisam使用前缀压缩来减少索引的大小,从而让更多的索引可以放入内存中,默认只压缩字符串,但通过参数配置也可以对整数做压缩,myisam压缩每个索引块的方法是,先完全保存索引块中的第一个值,然后将其 ...
- MySql + EF6 + .Net Core
2016年8月17日01:21:29 更新:这里介绍一下一个开源的 EF Core 的 MySQL 组件 [MySQL for .NET Core - Pomelo 扩展包系列][http://www ...
- lipo 合并target为Simulator和Device编译的静态库
进入项目对应的Build目录后,以下指令: $lipo -create Debug-iphoneos/libSalamaDeveloper.a Debug-iphonesimulator/libSal ...
- Android 进阶 Android 中的 IOC 框架 【ViewInject】 (下)
上一篇博客我们已经带大家简单的吹了一下IoC,实现了Activity中View的布局以及控件的注入,如果你不了解,请参考:Android 进阶 教你打造 Android 中的 IOC 框架 [View ...