wpf中UserControl的几种绑定方式

原文: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、完全可重用的控件

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

  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、小结

实际开发的过程中,大部分的情况是1+3,即完全不重用+部分重用的控件。即使遇到完全重用的控件,也不大会形成级联。

原文地址:https://www.cnblogs.com/lonelyxmas/p/12329518.html

时间: 2024-10-12 18:43:38

wpf中UserControl的几种绑定方式的相关文章

在WPF中UserControl

在这里我们将将打造一个UserControl(用户控件)来逐步讲解如何在WPF中自定义控件,并将WPF的一些新特性引入到自定义控件中来.我们制作了一个带语音报时功能的钟表控件, 效果如下: 在VS中右键单击你的项目,点击"添加新项目",在出现的选择列表中选择"UserControl",VS会自动为你生成一个*.xaml文件以及其对应的后台代码文件(*.cs或其它).值得注意的是,自动生成的代码中,你的控件是继承于System.Windows.Controls.Use

正确处理WPF中Slider值改变事件的方式

最近在用WPF数据绑定重写一下播放器项目时遇到的关于Slider的问题,在窗体透明度调节和播放进度调节上用了Slider控件.调节窗体透明度我是 这么想的:将窗体的Opacity属性的值与Slider的值绑定不就可以了,Opacity="{Binding ElementName=Slider,Path=Value,Mode=OneWay}",这样根本不用处理Slider的值改变事件 (ValueChanged).不过我要做保存设置的功能,因此肯定要记录Slider的值咯,于是处理一下V

call apply bind 的区别,this的四种绑定方式

1. apply()中有两个参数,不一定是必填项,当第一个参数什么都不填或则是null/undefined,默认为window 第二个参数必须是数组,数组中的元素和函数的参数对应 Call怎么使用 用途,用于修改函数中的this指向 也是函数ming.call(),执行的元素先替换函数中的this,然后再执行这个函数 Call中参数的分析1. call函数的第一个参数是什么,函数中this就换成什么,当不填或null/undefined,里面的this就是window2. 从第二参数开始,跟函数

jQuery中的Ajax几种请求方式

1. load( url, [data], [callback] ) :载入远程 HTML 文件代码并插入至 DOM 中. url (String) : 请求的HTML页的URL地址. data (Map) : (可选参数) 发送至服务器的 key/value 数据. callback (Callback) : (可选参数) 请求完成时(不需要是success的)的回调函数. 这个方法默认使用 GET 方式来传递的,如果[data]参数有传递数据进去,就会自动转换为POST方式的.jQuery

【学习笔记】——原生js中常用的四种循环方式

一.引言 本文主要是利用一个例子,讲一下原生js中常用的四种循环方式的使用与区别: 实现效果: 在网页中弹出框输入0   网页输出"欢迎下次光临" 在网页中弹出框输入1   网页输出"查询中--" 在网页中弹出框输入2   网页输出"取款中--" 在网页中弹出框输入3   网页输出"转账进行中--" 在网页中弹出框输入其他字符   网页输出"无效按键" 四种循环: for循环 while循环 for  in

MVC中CheckBoxList的3种实现方式

比如,当为一个用户设置角色的时候,角色通常以CheckBoxList的形式呈现.用户和角色是多对多关系: using System.Collections.Generic; using System.ComponentModel.DataAnnotations; namespace MvcApplication2.Models { public class User { public int Id { get; set; } [Display(Name = "用户名")] public

WPF中的命令与命令绑定导航

1.WPF中的命令与命令绑定(一) (引入命令) 2.WPF中的命令与命令绑定(二)(详细介绍命令和命令绑定) WPF中的命令与命令绑定导航

Springboot中IDE支持两种打包方式,即jar包和war包

Springboot中IDE支持两种打包方式,即jar包和war包 打包之前修改pom.xml中的packaging节点,改为jar或者war    在项目的根目录执行maven 命令clean package -Dmaven.test.skip=true,即可打包,如下 命令执行成功后,在target目录下即可看到打包好的文件 提示:若打的包为jar包,可通过java -jar guns-xxx.jar来启动Guns系统 原文地址:https://www.cnblogs.com/mracale

JAVA中单例模式的几种实现方式

1 线程不安全的实现方法 首先介绍java中最基本的单例模式实现方式,我们可以在一些初级的java书中看到.这种实现方法不是线程安全的,所以在项目实践中如果涉及到线 程安全就不会使用这种方式.但是如果不需要保证线程安全,则这种方式还是不错的,因为所需要的开销比较小.下面是具体的实现代码: 转http://www.cnblogs.com/CodeGuy/p/3580486.html public Class Singleton { private static Singleton instance