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

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. jquery 图片懒加载

      jquery 图片懒加载 CreationTime--2018年7月1日14点45分 Author:Marydon 1.源码展示 (function(a){a.fn.lazyload=functi ...

  2. 用PL/pgSQL写postgreSQL的存储过程[转]

    http://blog.chinaunix.net/uid-7591044-id-1742967.html 今天学会了用 PL/pgSQL 写 postgreSQL 的存储过程,网上资料实在少得可怜, ...

  3. 导入项目出现: Unable to resolve target ‘android-10′ 解决办法

    进入到android项目根目录下,打开项目文件project.properties ,修改 target=android-10  的值.把10改为当前虚拟机API level的版本即可.我这里改为17 ...

  4. python笔记-print输出

    print语句默认是输出一行后添加一个换行符 >>> for item in ['apple','ibm','google','oracle']: ... print item .. ...

  5. unity, do nothing的state

    要想在animator的stateMachine中建一个"doNothing",要注意:为了保证"doNothing"state能正常运转,不被无故跳过, Mo ...

  6. 云中的机器学习:FPGA 上的深度神经网络

    人工智能正在经历一场变革,这要得益于机器学习的快速进步.在机器学习领域,人们正对一类名为“深度学习”算法产生浓厚的兴趣,因为这类算法具有出色的大数据集性能.在深度学习中,机器可以在监督或不受监督的方式 ...

  7. 【Android】15.5 例15-3—Notification的各种属性演示

    分类:C#.Android.VS2015: 创建日期:2016-02-29 一.简介 利用这个例子,可测试通知的各种属性以及这些不同属性选项呈现的效果. 另外,在这个例子中,还演示了如何读写SD中的图 ...

  8. sed n/N使用说明

    sed的语法格式: sed [option] {sed-command} {input-file} sed在正常情况下,将处理的行读入模式空间(pattern space),脚本中的“sed-comm ...

  9. CLoadScene类

    #ifndef __LOADSCENE_H__ #define __LOADSCENE_H__ #include "GameFrameHead.h" class CGameScen ...

  10. Nginx 1.5.2 + PHP 5.5.1 + MySQL 5.6.10 在 CentOS 下的编译安装

    最近配置了几台Web服务器,将安装笔记贴出来吧.没时间像以前那样,将文章写的那样系统了,请见谅.详细配置,可以看以前的旧文章: http://blog.zyan.cc/nginx_php_v6 .安装 ...