WPF利用依赖属性和命令编写自定义控件

以实例讲解(大部分讲解在代码中)


1,新建一个WPF项目,添加一个用户控件之后在用户控件里面添加几个控件用作测试,

<UserControl x:Class="SelfControlDenpendy.SelfControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <StackPanel Width="200" Height="250" Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center">
            <TextBox Width="180" Height="50" x:Name="id" Margin="5"></TextBox>
            <TextBox Width="180" Height="50" Text="{Binding ElementName=id,Path=Text}" Margin="5"></TextBox>
            <Button Height="26" Width="120" x:Name="show" Margin="5" Content="测试绑定控件自身命令"
                    Command="{Binding ChangedIndexCommand}"
                    CommandParameter="{Binding ElementName=id,Path=Text}"></Button>
            <Button Height="26" Width="120" x:Name="buttonout" Margin="5"
                    Command="{Binding ButtonCommend, Mode=TwoWay}" Content="测试绑定外部命令" ></Button>
        </StackPanel>
    </Grid>
</UserControl>

  2,打开用户控件后台代码编写依赖属性以及命令(需要引入GalaSoft.MvvmLight.dll)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace SelfControlDenpendy
{
    /// <summary>
    /// SelfControl.xaml 的交互逻辑
    /// </summary>
    public partial class SelfControl : UserControl
    {
        public SelfControl()
        {
            InitializeComponent();
            DataContext = this;//注意此处用于绑定的源必须写,也可把所有依赖代码写在ViewModel里面
            ChangedIndexCommand= new RelayCommand<string>(AutoPaging);//注意带参数的命令的写法
        }
          void AutoPaging(string s)//命令执行带参数的方法
        {
            MessageBox.Show(s);
        }
    static SelfControl()//依赖属性的赋值必须写在静态函数里面因为是依赖属性静态只读在家上此处需要在初始化时就注册依赖属性古写在此处
        {               //也可不写在此处而写在字段定义出对其直接赋值
           UIPropertyMetadata md = new UIPropertyMetadata("", PropertyInputNameChanged);//第一个参数代表默认值(注意类型)
           SelfControl.InputNameProperty = DependencyProperty.Register("InputName", typeof(string), typeof(SelfControl), md);//最后一个参数用于当依赖属性值改变是调用md指定的方法
           ChangedCommandProperty =//内部访问命令
           DependencyProperty.Register("ChangedCommand", typeof(ICommand), typeof(SelfControl), new PropertyMetadata(null));//不许要默认值时写null或不要最后一个参数
           ButtonCommendProperty =//外部绑定命令
           DependencyProperty.Register("ButtonCommend", typeof(ICommand), typeof(SelfControl), new PropertyMetadata(null));
        }



       public ICommand ButtonCommend
       {
         get { return (ICommand)GetValue(ButtonCommendProperty); }
         set { SetValue(ButtonCommendProperty, value); }
       }
        public ICommand ChangedCommand
       {
         get { return (ICommand)GetValue(ChangedCommandProperty); }
         set { SetValue(ChangedCommandProperty, value); }
       }
        public static readonly DependencyProperty ChangedCommandProperty;//可以不用敲代码只用输入propdp按Tab即可完成编写
        public static readonly DependencyProperty InputNameProperty;
        public static readonly DependencyProperty ButtonCommendProperty;
        public string InputName
        {
            get { return (string)GetValue(SelfControl.InputNameProperty); }
            set { SetValue(SelfControl.InputNameProperty, value); }
        }
       

        private static void PropertyInputNameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)//此方法非常重要可用于编写逻辑代码
        {
          
            SelfControl sc = (SelfControl)d;

            string str = (string)e.NewValue;//外部赋给依赖属性的值(注意依赖属性的类型)

            if (str != "" && str != null)
            {
                sc.id.Text = str.ToString();
            }
        }
    }
    }
}

  3,在主窗口中就可以使用此用户控件(注意引入命名空间)

<Window x:Class="Dependency.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:loac="clr-namespace:Dependency"
        Title="MainWindow" Height="350" Width="600">
    <Grid>
        <TextBox x:Name="tt" Margin="428,70,32,208"></TextBox>
        <loac:SelfControl x:Name="sc" Margin="10,10,189,60" RenderTransformOrigin="0.456,0.7" 
                          ButtonCommend="{Binding AutoCommand}"></loac:SelfControl>
        <Button x:Name="bt" Margin="225,283,49,0" Content="测试依赖属性" Click="bt_Click"></Button>
    </Grid>
</Window>

  4,后台逻辑代码

using GalaSoft.MvvmLight.Command;
using System.Windows;
using System.Windows.Input;

namespace Dependency
{
    public partial class MainWindow : Window
    {
  
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
            AutoCommand = new RelayCommand(showcommend);//不带参数的命令
            AddUserCommand = new RelayCommand(ExecuteAddUser, CanExecuteAddUser);//添加判断的命令
            bt.Command = AutoCommand;//赋值命令,用于关联命令
            sc.ButtonCommend = AutoCommand;//关联依赖命令
        }
        void showcommend()
        {
            MessageBox.Show("测试");
        }
        public ICommand AutoCommand { get; private set; }
        private ICommand m_ButtonCommand;//此处并未使用此命令,只是显示一般命令的写法
        public ICommand ButtonCommand
        {
            get
            {
                return m_ButtonCommand;
            }
            set
            {
                m_ButtonCommand = value;
            }
        }
        public ICommand AddUserCommand { get; private set; }
        void ExecuteAddUser()
        {
            //逻辑代码
        }
        bool CanExecuteAddUser()
        {
            //逻辑代码
            return true;
        }
        private void bt_Click(object sender, RoutedEventArgs e)
        {
            sc.InputName = tt.Text.ToString();
            AutoCommand.Execute(null);//执行定义的命令可代替bt.Command = AutoCommand;
        }
    }
}

  1,若出现在XAML使用用户控件依赖命令时出现“未识别或无法访问”的提示时重新编译或生成一下即可

     2,有可能出现把自定义命令赋值给用户控件的命令但是出现没有调用执行方法,此时建议改用绑定关联,或检查用户控件中使用命令的位置是否合适

     3,依赖属性的默认值类型错误,注意修改依赖属性注册处的最后一个参数

原文地址:https://www.cnblogs.com/wangboke/p/5359051.html