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

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. MyEclipse连接sqlserver2008具体流程

    参照这里: 图形连接  http://wenku.baidu.com/view/f50838086c85ec3a87c2c53a.html 还有查看的是这个:   2. 重新用Window验证方式登陆 ...

  2. 解析_theme_build_registry()和_theme_process_registry()

    Drupal使用_theme_build_registry()和_theme_process_registry()两个函数构建theme registry.theme registry是theme h ...

  3. ThinkPHP实现事务回滚示例代码(附加:PDO的事务处理)

    ThinkPHP的事务回滚示例如下: $m=D('YourModel');//或者是M(); $m2=D('YouModel2'); $m->startTrans();//在第一个模型里启用就可 ...

  4. ubuntu sudo 和su的区别

    ubuntu用户管理 sudo意思就是super-user do,让当前用户暂时以管理员的身份root来执行这条命令. su是用来改变当前用户的,su root,就是将当前用户切换为root,用了su ...

  5. python 并发和线程

    并发和线程 基本概念 - 并行.并发 并行, parallel 互不干扰的在同一时刻做多件事; 如,同一时刻,同时有多辆车在多条车道上跑,即同时发生的概念. 并发, concurrency 同时做某些 ...

  6. HDU 3746 数据结构之KMP

    pid=3746">点击打开链接 题意:给T组数据,每组一个字符串,问最少加入多少个字符能够使这个串变成一个子串连续出现的串 思路:利用KMP的next数组进行变换,next数组保存的 ...

  7. python pivot() 函数

    以下为python pandas 库的dataframe pivot()函数的官方文档: Reshape data (produce a “pivot” table) based on column ...

  8. Hadoop-2.2.0中文文档—— Shell命令

    FS Shell 调用文件系统(FS)Shell命令应使用 bin/hadoop fs <args>的形式. 全部的的FS shell命令使用URI路径作为參数.URI格式是scheme: ...

  9. ubuntu下禁用和恢复触摸板

    1.一般禁用选项在 settings > mouse and touchpad 中.(16.04通过实验)如果无法禁用或者希望恢复,向下看. 2.命令行键入: xinput ,插卡touchpa ...

  10. Linux Kernel源码浏览

    https://www.kernel.org/http://lxr.linux.no/