星空雅梦

WPF自定义命令

自定义命令,可以分为两个层次来理解

1.声明自己的RoutedCommand实例,这个层次比较浅

2.从实现ICommand接口开始,这个才算的上真正的自定义命令

自定义命令的目的是为了把业务逻辑转移到命令内部,而不是需要捕捉到命令之后再回过头去处理。

要想自定义命令,就不能不了解命令系统的几个要素:

1.命令(Command):WPF的命令实际上就是实现了ICommand接口的类,平时使用最多的就是RoutedCommand类.

2.命令源(Command Source):命令的发送者,是实现了ICommandSource的类,平时用的Button就实现了这个接口

3.命令目标(Command Target):即命令将发送给谁,或者说命令的作用对象,是实现了IINputElement的类

4.命令关联(Command Binding):负责把一些外围逻辑与命令关联起来,比如执行之前对命令是否可以执行进行判断,命令执行之后还有那些后续工作

了解了命令系统的几个要素,就可以自己定义命令了

1.定义接口

为了规范我们的命令源,更统一的通过命令来调用,我们约定一个接口,所有使用该命令的命令源必须是实现了该接口的类型。

interface IView

{
//是否更改
bool IsChanged { get; set; }

//方法
void SetBinding();
void Refresh();
void Clear();
void Save();
}

复制代码
interface IView
    {
        //是否更改
        bool IsChanged { get; set; }

        //方法
        void SetBinding();
        void Refresh();
        void Clear();
        void Save();
    }
复制代码

2.定义命令

创建一个专门用于处理IView接口派生类的命令。我们说,命令就是实现了ICommand接口的类,接口包含两个方法,一个委托事件,我们这里只实现Excute方法

class ClearCommand:ICommand
{

public bool CanExecute(object parameter)
{
throw new NotImplementedException();
}

public event EventHandler CanExecuteChanged;

public void Execute(object parameter)
{
IView view = parameter as IView;
//这里体现了我们的业务逻辑
view.Clear();
}
}

3.定义命令源

有了命令,下一步定义发送命令的命令源

class MyCommandSource:UserControl,ICommandSource
{
//命令
public ICommand Command{ get;set; }
//参数
public object CommandParameter { get; set; }
//目标
public System.Windows.IInputElement CommandTarget { get; set; }

protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);

//执行命令
if (this.Command != null)
{
//目标作为参数
Command.Execute(this.CommandTarget);
}
}
}

4.定义命令的目标

命令目标有两个限制,一个是实现IInputElement,另一个是我们定义的,要求实现接口IView

分为两部分 一部分是XAML

<UserControl x:Class="CommandTest2.MiniView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="120" Width="200">
<Grid>
<Border CornerRadius="5" BorderBrush="LawnGreen" BorderThickness="2">
<StackPanel>
<TextBox x:Name="txt1" Margin="5"></TextBox>
<TextBox x:Name="txt2" Margin="5"></TextBox>
<TextBox x:Name="txt3" Margin="5"></TextBox>
<TextBox x:Name="txt4" Margin="5"></TextBox>
</StackPanel>
</Border>
</Grid>
</UserControl>

另一部分是后台代码

namespace CommandTest2
{
/// <summary>
/// MiniView.xaml 的交互逻辑
/// </summary>
public partial class MiniView : UserControl,IView
{
public MiniView()
{
InitializeComponent();
}

public bool IsChanged
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}

public void SetBinding()
{
throw new NotImplementedException();
}

public void Refresh()
{
throw new NotImplementedException();
}

public void Save()
{
throw new NotImplementedException();
}

public void Clear()
{
txt1.Clear();
txt2.Clear();
txt3.Clear();
txt4.Clear();
}
}
}

这样,我们需要的几个部分凑齐,就可以使用了

窗体代码

<Window x:Class="CommandTest2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CommandTest2"
Title="Command" Height="205" Width="250">
<StackPanel>
<local:MyCommandSource x:Name="ctrlClear" Margin="10">
<TextBlock Text="清除" FontSize="16" TextAlignment="Center"
Background="LightGreen" Width="80"></TextBlock>
</local:MyCommandSource>
<local:MiniView x:Name="miniView"></local:MiniView>
</StackPanel>
</Window>


复制代码
<Window x:Class="CommandTest2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:CommandTest2"
        Title="Command" Height="205" Width="250">
    <StackPanel>
        <local:MyCommandSource x:Name="ctrlClear" Margin="10">
            <TextBlock Text="清除" FontSize="16" TextAlignment="Center"
                       Background="LightGreen" Width="80"></TextBlock>
        </local:MyCommandSource> 
        <local:MiniView x:Name="miniView"></local:MiniView>
    </StackPanel>
</Window>
复制代码

后台调用也很简单

ClearCommand clrCommand = new ClearCommand();
            
ctrlClear.Command = clrCommand;
ctrlClear.CommandTarget = miniView;

ClearCommand clrCommand = new ClearCommand();
            
ctrlClear.Command = clrCommand;
ctrlClear.CommandTarget = miniView;

参考《深入浅出WPF》刘铁猛 第9章

ps.工作需要,开始学习WPF,感觉跟ASP.NET还是有很多不一样的,在这里记录一下学习的历程,以便今后回顾之用,看如何一步步走的,走向何方

原文地址:https://www.cnblogs.com/LiZhongZhongY/p/10896668.html