• 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,即完全不重用+部分重用的控件。即使遇到完全重用的控件,也不大会形成级联。


    作者:AlexanderYao
    出处:http://alexanderyao.cnblogs.com/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    java中abstract详解
    java synchronized详解
    java单列设计模式 小记
    java中static 和 final 的一些使用规则
    Java cookie和session介绍与区别
    java中string stringbuilder stringbuffer 的区别
    java中final的作用
    报错信息:ORA-00979:不是GROUP BY表达式
    解决异常信息 Caused by: java.lang.IllegalArgumentException: invalid comparison: java.lang.String and java.util.Date
    spring boot 集成 mybatis 单元测试Dao层 控制台报错:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):
  • 原文地址:https://www.cnblogs.com/bruce1992/p/14141576.html
Copyright © 2020-2023  润新知