要开始使用命令,必须做三件事:

一:定义一个命令

二:定义命令的实现

三:为命令创建一个触发器

WPF中命令系统的基础是一个相对简单的ICommand的接口,代码如下:

public interface ICommand 
{
event EventHandler CanExecuteChanged;
bool CanExecute(object parameter);
void Execute(object parameter);
}

CanExecute用于确定命令是否处于可执行的状态。典型的,UI控件能使用CanExecute来启用或禁用自己。也就是说,在相关的命令从CanExecute中返回False的时候,按钮将变得不可用。

Execute是命令的关键,当被调用时,它将触发命令的执行。

要定义一个新命令,可以实现ICommand接口。如希望ICommand在被调用后关闭应用程序,代码如下:

public class Exit : ICommand {
event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
Application.Current.Shutdown();
}
}

要把一个菜单项绑定到应用程序关闭这个命令上,可以把他们的Command属性挂到Exit命令上,代码如下:

<MenuItem Header="_File">
<MenuItem Header="_Exit">
<MenuItem.Command>
<local:Exit/>
</MenuItem.Command>
</MenuItem>
</MenuItem>


由于把命令用于多个位置比较常见,所以创建一个存储命令的静态字段也常见:

public static readonly ICommand ExitCommand = new Exit();

这样做的好处是,通过这个类型为ICommand的字段,可以让Exit命令的实现完全私有化。现在,可以把Exit标记为私有类,并把标记转化为绑定到静态字段,代码如下:

        <MenuItem Header="_File">
<MenuItem Header="_Exit" Command="{x:Static local:WinCommand.ExitCommand}"/>
</MenuItem>

下面我们通过添加一个和Close命令挂接的按钮,可以为窗口编写一个模板,以实现关闭窗口的功能,代码如下:

 <Window.Style>
<Style TargetType="Window"> <Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Window">
<DockPanel>
<StatusBar DockPanel.Dock="Bottom">
<StatusBarItem>
<Button
Command="{x:Static ApplicationCommands.Close}">Close</Button>
</StatusBarItem>
</StatusBar>
<ContentPresenter/>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Style>

我们接着要通过把命令绑定添加到窗口中让窗口关闭。

  /// <summary>
/// WinCommand.xaml 的交互逻辑
/// </summary>
public partial class WinCommand : Window
{
public static readonly ICommand ExitCommand = new Exit();
public WinCommand()
{
InitializeComponent(); CommandBindings.Add(
new CommandBinding(
ApplicationCommands.Close,
CloseExecuted)); } void CloseExecuted(object sender, ExecutedRoutedEventArgs e)
{
this.Close();
} }

使用命令可以清晰地把显示和行为分开。通过使用单一的名称为所需的语义动作签名,在尝试把多个控件和单个事件处理过程挂接起来的时候,可以避免很多由此引发的紧耦合问题。通常,应用程序逻辑应该总是通过命令的方式来实现的,而不是事件处理程序。对于很多需要直接挂接到事件处理过程上的常见例子,用触发器来处理更好。

命令与数据绑定

使用命令的一个令人振奋和强大的特性 就是和数据绑定集成。由于Command和CommandParameter都是元素上的属性,所以他们都能被设置为一些绑定到他们的数据。因此,可以使用绑定的数据内容来确定应该发生的动作。

为了演示他们是如何融合到一起的,将以C:\下面的文件的应用程序来开头。首先,定义一个显示内容的ListBox,和一个显示了每个文件名的数据模板,代码如下:

<ListBox Margin="2" Name="lbFile">

<ListBox.ItemTemplate>

<DataTemplate>

<TextBlock Text="{Binding Path=Name}"/>

</DataTemplate>

</ListBox.ItemTemplate>

</ListBox>

 

在后台,把ItemSource属性设置为文件列表:


public WinCommandAndBinding()
{
InitializeComponent(); FileInfo[] fileList = new DirectoryInfo("C:\\").GetFiles("*.*"); lbFile.ItemsSource = fileList;
}


运行如下:

现在,再添加一个按钮用来显示文件,但不希望任何文件都被打开。所以,要在加载的文件上提供某种类型的过滤器。现实现两个命令Open和Blocked并为他们提供某种类型的处理过程,代码如下:

  public static readonly RoutedCommand OpenCommand =
new RoutedCommand("Open", typeof(WinCommandAndBinding)); public static readonly RoutedCommand BlockedCommand =
new RoutedCommand("Blocked", typeof(WinCommandAndBinding)); public WinCommandAndBinding()
{
InitializeComponent(); CommandBindings.Add(new CommandBinding (OpenCommand,
delegate(object sender,ExecutedRoutedEventArgs e){
Process.Start("notepad.exe",(string)e.Parameter);})); CommandBindings.Add(new CommandBinding(BlockedCommand,
delegate(object sender, ExecutedRoutedEventArgs e)
{
MessageBox.Show((string)e.Parameter, "Blocked");
})); FileInfo[] fileList = new DirectoryInfo("C:\\").GetFiles("*.*");
lbFile.ItemsSource = fileList;
}
}

在定义好两个命令后,就可以更新文件的数据模板来包含按钮了。在命令参数(文件名)中使用数据绑定。对应命令本身,由于希望某些条目用OpenCommand,而其他条目用BlockedCommand,所以将使用IValueConvert把文件名转换为ICommand,代码如下:

 <ListBox Margin="2" Name="lbFile">
<ListBox.ItemTemplate>
<DataTemplate>
<WrapPanel>
<TextBlock Text="{Binding Path=Name}"/>
<Button Margin="5" CommandParameter="{Binding Path=FullName}">
<Button.Command>
<Binding>
<Binding.Converter>
<local:FileToCommandConverter/>
</Binding.Converter>
</Binding>
</Button.Command> Show
</Button>
</WrapPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

下面是转换器:

    public class FileToCommandConverter : IValueConverter
{
public object Convert(object value ,Type targetType,object parameter,CultureInfo culture)
{
string ext = ((FileInfo)value).Extension.ToLowerInvariant();
if (ext == ".txt")
return WinCommandAndBinding.OpenCommand;
else
return WinCommandAndBinding.BlockedCommand;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}

运行结果:

这个例子虽然有点微不足道,不过可以使用CanExecute方法轻松地完成类似的行为,并针对“坏”文件禁用这个命令。然而,这里最重要的一点是,可以返回任何命令。可以使用任何基于数据的逻辑来确定任何元素的行为。

另外我们可以考虑下能不能用数据触发器实现呢?呵呵,可以的,这等于把命令、数据绑定和触发器三者融合到一起了?是不是很强大,呵呵下面是代码:

 <ListBox Margin="2" Name="lbFile2">
<ListBox.ItemTemplate>
<DataTemplate>
<WrapPanel>
<TextBlock Text="{Binding Path=Name}"/>
<Button x:Name="btnShow" Margin="5" CommandParameter="{Binding Path=FullName}"
Command="{x:Static local:WinCommandAndBinding.BlockedCommand}"
Content=" Block"/>
</WrapPanel>
<DataTemplate.Triggers>
<DataTrigger Value=".txt">
<DataTrigger.Binding>
<Binding Path='Extension'>
<Binding.Converter>
<local:ToLowerInvariantConvert/>
</Binding.Converter>
</Binding>
</DataTrigger.Binding>
<Setter TargetName="btnShow"
Property="Command"
Value="{x:Static local:WinCommandAndBinding.OpenCommand}"/>
<Setter TargetName="btnShow" Property="Content" Value="Show"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>


转换器:
    public class ToLowerInvariantConvert : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return ((string)value).ToLowerInvariant(); }
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}


如果感觉不错的话,请帮忙推荐,谢谢……

WPF命令(Command)介绍、命令和数据绑定集成应用的更多相关文章

  1. WPF自学入门(十一)WPF MVVM模式Command命令 WPF自学入门(十)WPF MVVM简单介绍

    WPF自学入门(十一)WPF MVVM模式Command命令   在WPF自学入门(十)WPF MVVM简单介绍中的示例似乎运行起来没有什么问题,也可以进行更新.但是这并不是我们使用MVVM的正确方式 ...

  2. WPF中的命令(Command)

    这节来讲一下WPF中的命令(Command)的使用. [认识Command] 我们之前说过,WPF本身就为我们提供了一个基础的MVVM框架,本节要讲的命令就是其中一环,通过在ViewModel中声明命 ...

  3. WPF自己定义命令Command

    一.自己定义命令 自己定义命令必需要实现ICommand接口.例如以下代码所看到的: /// <summary> /// 自己定义的清除命令. 光脚丫思考 2014-7-31 06:51: ...

  4. WPF之事件绑定命令

    目录 事件绑定意义 无参数的事件绑定 带EventArgs参数的事件绑定 使用事件绑定 扩展:基于InvokeCommandAction源码的实现(推荐) 参考资料 事件绑定意义 一般事件的处理程序都 ...

  5. linux配置网卡IP地址命令详细介绍及一些常用网络配置命令

    linux配置网卡IP地址命令详细介绍及一些常用网络配置命令2010-- 个评论 收藏 我要投稿 Linux命令行下配置IP地址不像图形界面下那么方 便,完全需要我们手动配置,下面就给大家介绍几种配置 ...

  6. linux常用命令的介绍

    本文主要介绍Linux常用命令工具,比如用户创建,删除,文件管理,常见的网络命令等 如何创建账号: 1. 创建用户 useradd -m username -m 表示会在/home 路径下添加创建用户 ...

  7. Command Pattern -- 命令模式原理及实现(C++)

    主要参考<大话设计模式>和<设计模式:可复用面向对象软件的基础>两本书.本文介绍命令模式的实现. What it is:Encapsulate a request as an ...

  8. .bat批处理命令的介绍

    HUC = = D组 http://www.cnhonkerarmy.com/ 63707869 =====================================开始============ ...

  9. 浅谈Windows环境下DOS及MS-DOS以及常见一些命令的介绍

    浅谈Windows环境下DOS及MS-DOS以及常见一些命令的介绍 前记 自己是搞编程的,首先我是一个菜鸟,接触计算机这么久了,感觉很多计算机方面的技术和知识朦朦胧胧.模模糊糊,貌似有些贻笑大方了:所 ...

随机推荐

  1. 二、基于kubernetes构建Docker集群环境实战

    kubernetes是google公司基于docker所做的一个分布式集群,有以下主件组成 etcd: 高可用存储共享配置和服务发现,作为与minion机器上的flannel配套使用,作用是使每台 m ...

  2. 【VB.NET】利用纯真IP数据库查询IP地址及信息

    几年前从某个博客抄来的,已经忘记原地址了,如果需要C#版的,可以在博客园搜到吧.我因为自己用,所以转换为了VBNET代码,而且也放置了很久,今天无意间翻出来,就分享给大家吧. 首先,先下载 纯真数据库 ...

  3. js css等静态文件版本控制,一处配置多处更新.net版【原创】

    日常web开发中,我们修改了js.css等静态资源文件后,如果文件名不变的话,客户端浏览并不会及时获取最新的资源文件,这就很尴尬了 怎么办呢? 1.小白:让客户清除缓存?,No ,  不靠谱 2.初级 ...

  4. C#通过字符串名称来调用对应字符串名称的方法

    前段时间在一个项目中,在一个地方要将函数所在类中的方法都调用一遍,但是否调用要通过配置文件中的内容决定.所以为了减少代码量,在网上查了相关信息,终于成功的将其应用到了项目中,我在这里将我做的一个简单例 ...

  5. cefsharp

    快速上手 js和C#互相调用. C#调用js比较容易.JS调用C#代码,现有两种方法.老方法的缺点是只支持单页,如果切换页面,原有创建的变量就失效了.新方法没有这些问题. 老方法: Cefsharp ...

  6. C# EPPlus导出EXCEL,并生成Chart表

    一  在negut添加EPPlus.dll库文件. 之前有写过直接只用Microsoft.Office.Interop.Excel 导出EXCEL,并生成Chart表,非常耗时,所以找了个EPPlus ...

  7. MS SQL的某一数据库成了Single User模式

    数据库恢复失败,原来的数据却变成了 当尝试打开数据库的属性,即出现上面图片异常的信息. 正常来说,是可以打开数据库的属性 此刻,你可以运行SQL语句来解决: USE master; GO ALTER ...

  8. python 数据类型三 (字典)

    一.字典的介绍 字典(dict)是python中唯一的一个映射类型,它是以{}括起来的键值对组成,在dict中key是唯一的,在保存的时候,根据key来计算出一个内存地址,然后将key-value保存 ...

  9. Django(命名URL和URL反向解析)

    day67 参考: https://www.cnblogs.com/liwenzhou/articles/8271147.html#autoid-1-4-0 反向解析URL             本 ...

  10. dubbo实现原理之动态编译

    Dubbo为了实现基于spi思想的扩展特性,特别是能够灵活添加额外功能,对于扩展或则策略选择的设配类能够动态生成.对于一些需求已知的类如Protocal,它们的设配类代码dubbo可以直接的提供,但是 ...