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

一、问题描述

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

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

<UserControl x:Class="CHC.AibirdGStationPro.Control.AppButton"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:CHC.AibirdGStationPro.Control"
        mc:Ignorable="d"
        Name="appButton" Height="auto" Width="auto" BorderThickness="0" Background="Transparent">
    <!--定义控件-->
    <Grid>
        <Button x:Name="myButton" Height="102" Width="102" Style="{StaticResource AppButtonStyle}" 
                MouseLeftButtonDown="Button_MouseLeftButtonDown"
                MouseLeftButtonUp="Button_MouseLeftButtonUp" Command="{Binding  Command }" CommandParameter="{Binding CommandParameter}"/>
    </Grid>
</UserControl>
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Imaging;

namespace CHC.AibirdGStationPro.Control
{
    /// <summary>
    /// AppButton.xaml 的交互逻辑
    /// </summary>
    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能做到这一点。

    <!--定义控件-->
    <Grid>
        <Button x:Name="myButton" Height="102" Width="102" Style="{StaticResource AppButtonStyle}" 
                MouseLeftButtonDown="Button_MouseLeftButtonDown"
                MouseLeftButtonUp="Button_MouseLeftButtonUp" 
                Command="{Binding  Command ,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type UserControl}},Mode=TwoWay}"
                CommandParameter="{Binding CommandParameter ,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type UserControl}},Mode=TwoWay}"/>
    </Grid>
 <control:AppButton x:Name="btnRoutePlanning" NormalImage="{StaticResource RoutePlanning}" FocusedImage="{StaticResource RoutePlanning_focused}" 
                                   Command="{Binding  Path=StartUpAppCommand}" CommandParameter="btnRoutePlanning"/>

小结:

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

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

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

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值