我们经常会抽取一些可重用的控件,某个属性是否需要重用,直接决定了这个属性的绑定方式。

1、完全不可重用的控件

有一些与业务强相关的控件,它们的属性完全来自ViewModel,越是相对复杂的控件,越容易这样。比如:

// ChooseUc.xaml
<UserControl>
<StackPanel Orientation="Horizontal">
<Label Content="选择一个水果: "/>
<ComboBox ItemsSource="{Binding Fruits}"/>
</StackPanel>
</UserControl>

使用的时候直接 <my:ChooseUc /> 即可直接绑定到ViewModel里的 List<Fruit> Fruits ,不用做额外的工作。好处是特别方便,代价是与vm完全耦合。

2、完全可重用的控件

类似的控件多了,就能抽出一些完全可重用的控件,这些控件与业务无关。为了实现这种重用性,要做到:

  1. 抽出所有可变的属性,定义在控件内部
  2. 绑定控件内定义的这些属性
  3. 外部使用时,再将这些属性与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、小结

wpf中用户控件的属性重用的更多相关文章

  1. WPF中用户控件对比自定义控件(UserControl VS CustomControl)

    接着这篇文章(http://www.cnblogs.com/shiyue/archive/2013/02/02/2889907.html)写: 用户控件(组合) 用于在一个项目中使用多次 自定义控件( ...

  2. WPF中常用控件的属性

    Source = new BitmapImage( new Uri( WangCaiConfig.GetCurrentDirectory() + imgStr, UriKind.RelativeOrA ...

  3. WPF中Image控件的Source属性

    原文:WPF中Image控件的Source属性 imgBook 是一个Image控件,在后台代码中我想给它指定Source的属性.我先如下方式进行: Uri uri = new Uri(strImag ...

  4. WPF中PasswordBox控件的Password属性的数据绑定

    原文:WPF中PasswordBox控件的Password属性的数据绑定 英文原文:http://www.wpftutorial.net/PasswordBox.html 中文原文:http://bl ...

  5. 浅尝辄止WPF自定义用户控件(实现颜色调制器)

    主要利用用户控件实现一个自定义的颜色调制控件,实现一个小小的功能,具体实现界面如下. 首先自己新建一个wpf的用户控件类,我就放在我的wpf项目的一个文件夹下面,因为是一个很小的东西,所以就没有用mv ...

  6. 示例:WPF中Slider控件封装的缓冲播放进度条控件

    原文:示例:WPF中Slider控件封装的缓冲播放进度条控件 一.目的:模仿播放器播放进度条,支持缓冲任务功能 二.进度: 实现类似播放器中带缓存的播放样式(播放区域.缓冲区域.全部区域等样式) 实现 ...

  7. Android中常用控件及属性

    在之前的博客为大家带来了很多关于Android和jsp的介绍,本篇将为大家带来,关于Andriod中常用控件及属性的使用方法,目的方便大家遗忘时,及时复习参考.好了废话不多讲,现在开始我们本篇内容的介 ...

  8. 对用户控件(ascx)属性(property)赋值

    对用户控件(ascx)属性(property)赋值 Insus.NET写此博文,是对用户控件(ASCX)的属性赋值经验与技巧分享.是这样子的,在做新闻站点时,一般都会有分很多类别. 在站点首页会显示最 ...

  9. WPF中TreeView控件SelectedItemChanged方法的MVVM绑定

    问题描述:左侧treeview控件中点击不同类别的节点时,右侧的页面会显示不同的权限.比如对于My Publications,拥有Modify和Delete两种权限,对于My Subscription ...

随机推荐

  1. LeetCode 110 Balanced Binary Tree(平衡二叉树)(*)

    翻译 给定一个二叉树,决定它是否是高度平衡的. (高度是名词不是形容词-- 对于这个问题.一个高度平衡二叉树被定义为: 这棵树的每一个节点的两个子树的深度差不能超过1. 原文 Given a bina ...

  2. MySQL5.6 主从复制 ERROR 1776 (HY000): Parameters MASTER_LOG_FILE

    主从都开启了gtid,在设置从库的时候遇到了问题 mysql> CHANGE MASTER TO MASTER_HOST=‘xxx’,MASTER_USER='replicant',MASTER ...

  3. 【LeetCode】117. Populating Next Right Pointers in Each Node II (2 solutions)

    Populating Next Right Pointers in Each Node II Follow up for problem "Populating Next Right Poi ...

  4. python模块介绍-locustio:性能测试工具locustio

    转自:http://automationtesting.sinaapp.com/blog/m_locustio_doc python测试文章 http://weibo.com/cizhenshi?is ...

  5. canvas 压缩图片的大小

    使用 signature_pad canvas 库生成的图片太大.但又没有提供方法来压缩. 当然这是根据你canvas的画布大小决定的,某些原因导致我的画布就得是那么大. 随随便便一个图片转化为bas ...

  6. API 版本控制的几种方式

    个人建议:用content type,即放在Header里面!比如加一个Version:1.4.3 这篇文章写得很好,介绍了三种实现web api版本化的三种方式.我从评论里又收集到两种方式,所以一共 ...

  7. sso单点登录研究

    iframe跨域通信的通用解决方案http://www.alloyteam.com/2012/08/lightweight-solution-for-an-iframe-cross-domain-co ...

  8. Android 依赖注入: Dagger 2 实例解说(一)

    本文原创,转载请注明出处:http://blog.csdn.net/zjbpku [Duplicated]   link to  Dagger on Android - Dagger2具体解释 关于D ...

  9. UIView总结

    转自:http://langhua9527.iteye.com/blog/1377741 如果想调用某个类的某个方法可以写成这样,这个方法来自NSObject类 performSelector: pe ...

  10. windows phone 应用提交商店失败总结

    应用完成后,在提交微软商店时,可能因为各种各样的问题导致提交审核失败.以前的审核失败并没有总结,希望今后 把各种提交审核失败的情况总结一下,以减少今后提交认证时浪费时间. 1.商店的屏幕截图上不能包含 ...