命令系统的基本元素和关系
WPF命令系统的组成要素:
A.命令(command):WPF命令实际上就是实习了ICommand接口的类。平时使用最多的就是RoutedCommand类。
B.命令源(command source):即命令的发送者,实现了ICommandSource接口的类。
C.命令目标(command Target):即命令发给了谁或理解为命令的接收者。命令目标必须是实现了IInputElement接口的类。
D.命令关联(command Binding):负责把一些外围逻辑和命令关联起来。比如执行之前对命令是否可以执行进行判、命令执行之后还有哪些后续工作等。

命令使用的步骤:
1.创建命令类
2.声明命名实例
3.指定命令源
4.指定命令目标
5.设置命令关联

ICommand接口与RoutedCommand
WPF中的命令是实现了ICommand接口的类。
ICommand接口非常简单,只包含两个方法一个事件。
<1>Execute方法:命令执行,或者说命令执行于命令目标之上。需要注意的是,现实世界中的命令是不会自己执行的,而这里,执行变成了命令的方法,有点拟人化的味道。
<2>CanExecute方法:在执行之前探知命令是否可以执行。
<3>CanExecuteChanged事件:当命令的可执行状态改变的时候,可激发此事件通知其它对象。

RoutedCommand就是一个实现了ICommand接口的类。
RoutedCommand在实现ICommand接口时,并未向Execute和CanExecute方法中添加任何逻辑,
也就是说,它是通用的、与具体的业务逻辑无关的。

<Window x:Class="命令1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel Background="Red" x:Name="sp1">
<Button x:Name="btn1" Content="Send Clear Command" Margin="5" Background="{Binding}"/>
<TextBox x:Name="txtA" Margin="5,0" Height="200"/>
</StackPanel>
</Window>
using System.Windows;
using System.Windows.Input; namespace 命令1
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent(); InitializeCommand();
} //1.创建命令类
//2.声明命名实例
//3.指定命令源—— 命令发送者
//4.指定命令目标——命令接收者
//5.设置命令关联 //声明并定义命令
private RoutedCommand RouutedCommand = new RoutedCommand("可输入非空字符", typeof(MainWindow)); private void InitializeCommand()
{
//把命令赋值给命令源,并定义快捷键
this.btn1.Command = RouutedCommand;
this.RouutedCommand.InputGestures.Add(new KeyGesture(Key.C, ModifierKeys.Alt));
//指定命令目标
this.btn1.CommandTarget = txtA; //创建命令关联
CommandBinding commandBinding = new CommandBinding();
commandBinding.Command = RouutedCommand;//只关注与rouutedCommand相关的命令
commandBinding.CanExecute += new CanExecuteRoutedEventHandler(cb_CanExecute);
commandBinding.Executed += new ExecutedRoutedEventHandler(cb_Execute);
//把命令关联安置在外围控件上
this.sp1.CommandBindings.Add(commandBinding);
} //当命令到达目标之后,此方法被调用
private void cb_Execute(object sender, ExecutedRoutedEventArgs e)
{
this.txtA.Clear();
//避免事件继续向上传递而降低程序性能
e.Handled = true;
} //当探测命令是否可执行的时候该方法会被调用
private void cb_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
if (string.IsNullOrEmpty(txtA.Text))
{
e.CanExecute = false;
}
else
{
e.CanExecute = true;
}
//避免事件继续向上传递而降低程序性能
e.Handled = true;
}
}
} //对于以上的代码,需要注意以下几点:
//第一,使用命令可以避免自己写代码判断Button是否可以用以及添加快捷键。 //第二,RountedCommand是一个与业务逻辑无关的类,只负责在程序中跑腿而并不对命令目标进行操作,
//TextBox并不是由它清空的。那么TextBox的情况操作是谁呢?答案是CommandBinding。
//因为无论是探测命令是否可以执行还是命令送达目标,都会激发命令目标发送路由事件,
//这些事件会沿着UI元素树向上传递,最终被CommandBinding所捕捉。
//本例中CommandBinding被安装在外围的StackPanel上,Commandbinding站在高处起一个侦听器的作用,
//而且专门针对rouutedCommand命令捕捉与其相关的事件。
//本例中,当CommandBinding捕捉到CanExecute就会调用cb_CanExecute方法。
//当捕捉到是Executed的时候,就调用cb_Execute事件。 //第三,因为CanExecute事件的激发频率比较高,为了避免降低性能,在处理完毕之后建议将e.Handle设置为true。
//第四,CommandBinding一定要设置在命令目标的外围控件上,不然无法捕捉CanExecute和Executed等路由事件。

实例二:

<Window x:Class="命令2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="24" />
<RowDefinition Height="4" />
<RowDefinition Height="24" />
<RowDefinition Height="4" />
<RowDefinition Height="24" />
<RowDefinition Height="4" />
<RowDefinition Height="*" />
</Grid.RowDefinitions> <!--命令和命令参数-->
<TextBlock HorizontalAlignment="Left" Name="textBlock1" Text="Name:" VerticalAlignment="Center" Grid.Row="0"/>
<TextBox x:Name="txtName" Margin="60,5,0,0" Grid.Row="0"/>
<Button Content="New Teacher" Grid.Row="2" Command="New" CommandParameter="Teacher"/>
<Button Content="New Student" Grid.Row="4" Command="New" CommandParameter="Student"/>
<ListBox Grid.Row="6" x:Name="lbInfos"/>
</Grid> <!--为窗体添加CommandBinding-->
<Window.CommandBindings>
<CommandBinding Command="New" CanExecute="CommandBinding_CanExecute" Executed="CommandBinding_Executed"/>
</Window.CommandBindings>
</Window>
using System.Windows;
using System.Windows.Input; namespace 命令2
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
//两个按钮都使用的是New命令,但分别使用的是Student和Teacher做为的参数。 public MainWindow()
{
InitializeComponent();
} /// <summary>
/// 当探测命令是否可执行的时候该方法会被调用
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
if (string.IsNullOrEmpty(txtName.Text))
{
e.CanExecute = false;
}
else
{
e.CanExecute = true;
}
//路由终止,提高系统性能
e.Handled = true;
} /// <summary>
/// 当命令到达目标之后,此方法被调用
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
if (e.Parameter.ToString() == "Student")
{
this.lbInfos.Items.Add(string.Format("New Student:{0} 好好学习,天天向上。", txtName.Text));
}
else if (e.Parameter.ToString() == "Teacher")
{
this.lbInfos.Items.Add(string.Format("New Teacher:{0} 学而不厌,诲人不倦。", txtName.Text));
}
//路由终止,提高系统性能
e.Handled = true;
}
}
}

实例三:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace 命令4
{
public interface IView
{
//属性
bool IsChanged { get; set; }
//方法
void SetBinding();
void Refresh();
void Clear();
void Save();
}
} using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input; namespace 命令4
{
public class ClearCommand : ICommand
{
//当命令可执行状态发送改变时,应当被激发
public event EventHandler CanExecuteChanged; //用来判断命令是否可以执行
public bool CanExecute(object parameter)
{
throw new NotImplementedException();
} //命令执行时,带有与业务相关的Clear逻辑
public void Execute(object parameter)
{
IView view = parameter as IView;
if (view != null)
{
view.Clear();
}
}
}
} using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows; namespace 命令4
{
public class MyCommandSource : UserControl, ICommandSource
{
/// <summary>
/// 继承自ICommand的3个属性
/// </summary>
public ICommand Command
{
get;
set;
} public object CommandParameter
{
get;
set;
} public IInputElement CommandTarget
{
get;
set;
} //在命令目标上执行命令,或者说让命令作用于命令目标
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
if (this.CommandTarget != null)
{
this.Command.Execute(CommandTarget);
}
}
}
}
<UserControl x:Class="命令4.UCMniView"
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">
<Border CornerRadius="5" BorderBrush="GreenYellow" BorderThickness="2">
<StackPanel>
<TextBox Margin="5" x:Name="txt1"></TextBox>
<TextBox Margin="5" x:Name="txt2"></TextBox>
<TextBox Margin="5" x:Name="txt3"></TextBox>
<TextBox Margin="5" x:Name="txt4"></TextBox>
</StackPanel>
</Border> </UserControl>
using System;
using System.Windows.Controls; namespace 命令4
{
/// <summary>
/// UserControl.xaml 的交互逻辑
/// </summary>
public partial class UCMniView : UserControl,IView
{
public UCMniView()
{
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 Clear()
{
this.txt1.Clear();
this.txt2.Clear();
this.txt3.Clear();
this.txt4.Clear();
} public void Save()
{
throw new NotImplementedException();
}
}
}
<Window x:Class="命令4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:命令4"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<local:MyCommandSource x:Name="myCommandSource1">
<TextBlock Text="清除" Width="80" FontSize="16" TextAlignment="Center" Background="LightGreen"/>
</local:MyCommandSource> <local:UCMniView x:Name="mniView1" />
</StackPanel> </Window>
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 命令4
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent(); ClearCommand clearCommand = new ClearCommand();
this.myCommandSource1.Command = clearCommand;
this.myCommandSource1.CommandTarget = mniView1;
}
}
}

WPF Demo19 命令、UC的更多相关文章

  1. WPF之命令浅谈

    一.认识命令 1.1命令的特点 提到“命令”,我们应该想到命令的发出者,命令的接受者,命令的内容,准备工作,完成任务,回报工作...与事件中的发送者,接受者,消息,处理,处理,处理一一对应,如果是单纯 ...

  2. WPF C# 命令的运行机制

    1.概述 1.1 WPF C# 命令的本质 命令是 WPF 中的输入机制,它提供的输入处理比设备输入具有更高的语义级别. 例如,在许多应用程序中都能找到的“复制”.“剪切”和“粘贴”操作就是命令. W ...

  3. WPF 的命令的自动刷新时机——当你 CanExecute 会返回 true 但命令依旧不可用时可能是这些原因

    原文:WPF 的命令的自动刷新时机--当你 CanExecute 会返回 true 但命令依旧不可用时可能是这些原因 在 WPF 中,你可以使用 Command="{Binding Walt ...

  4. WPF 跟踪命令和撤销命令(复原)

    WPF 命令模型缺少一个特性是复原命令.尽管提供了一个 ApplicationCommands.Undo 命令,但是该命令通常被用于编辑控件(如 TextBox 控件),以维护它们自己的 Undo 历 ...

  5. WPF 自定义命令 以及 命令的启用与禁用

    自定义命令:     在WPF中有5个命令类(ApplicationCommands.NavigationCommands.EditingCommands.ComponentCommands 以及 M ...

  6. WPF自定义命令

    WPF的自定义命令实现过程包括三个部分,定义命令.定义命令源.命令调用,代码实现如下: public partial class MainWindow : Window { public MainWi ...

  7. 按键(ESC ,F1,F2等)——wpf的命令处理方法

    WPF窗体的命令绑定   方法一:使用代码 <WpfUI:View.CommandBindings> <CommandBinding Command="Help" ...

  8. WPF 之命令(七)

    一.前言 ​ 事件的作用是发布和传播一些消息,消息送达接收者,事件的使命也就完成了,至于消息响应者如何处理发送来的消息并不做规定,每个接收者可以使用自己的行为来响应事件.即事件不具有约束力. ​ 命令 ...

  9. WPF——执行命令清空文本框

    一.造一个窗体,在窗体里面先造一个StackPanel,然后再StackPanel里面放好按钮和文本框,注意给所有的控件和容器起名字 <Grid> <StackPanel Name= ...

随机推荐

  1. 【转载】 深度强化学习处理cartpole为什么reward很难超过200?

    原贴地址: https://www.zhihu.com/question/266493753 一直在看强化学习方面的内容,cartpole是最简单的入门实验环境,最原始的评判标准是连续100次epis ...

  2. php在foreach中使用引用赋值&可能遇到的问题(转)

    楼主在写项目的时候,由于初涉PHP的赋值引用操作,觉得这个功能非常强大,用时一时爽,没有深入了解过其中的原理,导致了一些当时觉得不可思议的BUG,废话不都说,我举个例子详细的描述一下这个问题. 代码: ...

  3. phpstorm使用zen coding 快速编辑补全html/css代码

    百科定义: 使用仿CSS选择器的语法来快速开发HTML和CSS ——由Sergey Chikuyonok开发. Zen Coding由两个核心组件组成:一个缩写扩展器(缩写为像CSS一样的选择器)和上 ...

  4. Groovy实现代码热载的机制和原理

    前言: 真的很久没在博客园上更新博客了, 现在趁这段空闲的时间, 对之前接触的一些工程知识做下总结. 先来讲下借用Groovy如何来实现代码的热载, 以及其中涉及到的原理和需要注意的点. 总的来说, ...

  5. 海康抓拍机SDK开发

    前言 项目采购的海康威视的抓拍机,需要首先获取抓拍图片,之后基于抓拍图片进行图像处理.本文基于海康SDK开发文档,按照开发步骤,咨询海康技术人员,现将开发过程记录如下. 主要过程的c++代码: /** ...

  6. #python str.format 方法被用于字符串的格式化输出。

    #python str.format 方法被用于字符串的格式化输出. #''.format() print('{0}+{1}={2}'.format(1,2,3)) #1+2=3 可见字符串中大括号内 ...

  7. 使用Python中的log模块将loss输出到终端与保存到文件

    记得之前对深度学习中得loss输出,经常自己会将输出流重新定向到一个文件中, 比如 python main.py > & | tee log.txt 对于caffe这种c++框架而言,用 ...

  8. sql ''增删改'' 笔记

    结构语言分类 DDL(数据定义语言)  create  drop  alter   创建删除以及修改数据库,表,存储过程,触发器,索引.... DML(数据操作语言)   insert  delete ...

  9. poj-1657 Distance on Chessboard

    c语言解决 代码:#include <stdio.h>#include <stdlib.h> int main(){    int num,i;    scanf(" ...

  10. python开发day02

    一 while循环 while 条件 代码块(循环体)  #:  判断条件是否为真,如果是真,则执行代码块, 然后再次回头判断条件是否为真,如果为真,则只执行代码块.......知道循环的判断出代码为 ...