WPF之自定义控件及添加依赖属性

一、问题描述

    我们要自定义一个Button,不使用任何原生Button的样式效果,所以,直接继承自UserControl而不是Button,但是又要具备Button的功能,所以,内部添加Button控件并重新设置样式模板,UserControl中没有Command和CommandParameter,所以,我们添加相应的依赖属性,并将其绑定到内部Button控件的Command和CommadParameter属性上,这样就能在外部像使用原生Button一样使用自定义Button设置Command和CommandParameter了。

    不过,现实还是很残酷的,当我们将自定义依赖属性绑定到内部Button上时,我们设置了自定义控件的this.DataContext = this;而当我们使用自定义控件时,要绑定的命令又存在于另一个外部的DataContext,一个控件只能有一个DataContext,于是矛盾产生了。


    
    
        
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Imaging;

namespace CHC.AibirdGStationPro.Control
{
    /// 
    /// AppButton.xaml 的交互逻辑
    /// 
    public partial class AppButton : UserControl
    {
        public AppButton()
        {
            InitializeComponent();
            this.DataContext = this;
        }

        public ICommand Command
        {
            get { return (ICommand)GetValue(CommandProperty); }
            set { SetValue(CommandProperty, value); }
        }
        // Using a DependencyProperty as the backing store for CommandProperty.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CommandProperty =
            DependencyProperty.Register("Command", typeof(ICommand), typeof(AppButton), new PropertyMetadata(null));

        public string CommandParameter
        {
            get { return (string)GetValue(CommandParameterProperty); }
            set { SetValue(CommandParameterProperty, value); }
        }
        // Using a DependencyProperty as the backing store for CommandParameterProperty.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CommandParameterProperty =
            DependencyProperty.Register("CommandParameter", typeof(object), typeof(AppButton), new PropertyMetadata(""));
    }
}

二、解决方案

方案一、在外部绑定Command时,不使用DataContext进行绑定,而使用ElementName,也就是先利用一个控件将要绑定的Command获取到,然后再间接绑定该控件的Command属性,以此完成对外部命令的绑定,但比较麻烦。

方案二、使用RelativeSource进行内部绑定,参考wpf 自定义控件中ElementName和DataContext之间的冲突

由于内部绑定时使用了this.DataContext = this,导致外部绑定不能使用外部DataContext,因此,如果内部绑定可以不使用DataContext,问题就能得到解决,而RelativeSource能做到这一点。

    
    
        
 

小结:

1、要实现数据绑定,关键是要设置好数据源,保证能够找到对应的数据,默认会从DataContext中查找,所以,DataContext一般都要设置,绑定自身属性时要设为this.DataContext = this。

2、RelativeSource通过根据控件类型查找相应的控件并绑定其属性,在自定义控件时很好解决了使用DataContext带来的问题。

3、自定义控件如果有自定义依赖属性,那应当将DataContext留给外部绑定,而不要在内部使用this.DataContext = this;

 

你可能感兴趣的:(WPF)