[UWP 自定义控件]了解模板化控件(7):支持Command
以我的经验来说,要让TemplatedControl支持Command的需求不会很多,大部分情况用附加属性解决这个需求会更便利些,譬如UWPCommunityToolkit的HyperlinkExtensions。
如果正在从头设计自定义控件并真的需要提供命令支持,可以参考这篇文章。支持Command的步骤比较简单,所以这篇文章比较简短。
要实现Command支持,控件中要执行如下步骤:
- 定义Command和CommandParameter属性。
- 监视Command的CanExecuteChanged事件。
- 在CanExecuteChanged的事件处理函数及CommandParameter的PropertyChangedCallback中,根据Command.CanExecute(CommandParameter)的结果设置控件的IsEnabled属性。
- 在某个事件(Click或者ValueChanged)中执行Command。
MenuItem是实现了Command支持的示例,重载了OnPointerPressed并且在其中执行Command:
public class MenuItem : Control
{
/// <summary>
/// 标识 Command 依赖属性。
/// </summary>
public static readonly DependencyProperty CommandProperty =
DependencyProperty.Register("Command", typeof(ICommand), typeof(MenuItem), new PropertyMetadata(null, OnCommandChanged));
private static void OnCommandChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
MenuItem target = obj as MenuItem;
ICommand oldValue = (ICommand)args.OldValue;
ICommand newValue = (ICommand)args.NewValue;
if (oldValue != newValue)
target.OnCommandChanged(oldValue, newValue);
}
/// <summary>
/// 标识 CommandParameter 依赖属性。
/// </summary>
public static readonly DependencyProperty CommandParameterProperty =
DependencyProperty.Register("CommandParameter", typeof(object), typeof(MenuItem), new PropertyMetadata(null, OnCommandParameterChanged));
private static void OnCommandParameterChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
MenuItem target = obj as MenuItem;
object oldValue = (object)args.OldValue;
object newValue = (object)args.NewValue;
if (oldValue != newValue)
target.OnCommandParameterChanged(oldValue, newValue);
}
public MenuItem()
{
this.DefaultStyleKey = typeof(MenuItem);
}
public event RoutedEventHandler Click;
/// <summary>
/// 获取或设置Command的值
/// </summary>
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
/// <summary>
/// 获取或设置CommandParameter的值
/// </summary>
public object CommandParameter
{
get { return (object)GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
}
protected virtual void OnCommandParameterChanged(object oldValue, object newValue)
{
UpdateIsEnabled();
}
protected virtual void OnCommandChanged(ICommand oldValue, ICommand newValue)
{
if (oldValue != null)
oldValue.CanExecuteChanged -= OnCanExecuteChanged;
if (newValue != null)
newValue.CanExecuteChanged += OnCanExecuteChanged;
UpdateIsEnabled();
}
protected virtual void UpdateVisualState(bool useTransitions)
{
if (IsEnabled)
{
VisualStateManager.GoToState(this, "Normal", useTransitions);
}
else
{
VisualStateManager.GoToState(this, "Disabled", useTransitions);
}
}
protected override void OnPointerPressed(PointerRoutedEventArgs e)
{
base.OnPointerPressed(e);
Click?.Invoke(this, new RoutedEventArgs());
if ((null != Command) && Command.CanExecute(CommandParameter))
{
Command.Execute(CommandParameter);
}
}
private void OnCanExecuteChanged(object sender, EventArgs e)
{
UpdateIsEnabled();
}
private void UpdateIsEnabled()
{
IsEnabled = (null == Command) || Command.CanExecute(CommandParameter);
UpdateVisualState(true);
}
}
以下是使用示例,作用是当TextBox的Text不为空时可以点击MenuItem,并且将Text作为MessageDialog的内容输出:
<StackPanel>
<TextBox x:Name="TextElement"/>
<local:MenuItem Command="{Binding}" CommandParameter="{Binding ElementName=TextElement,Path=Text}"/>
</StackPanel>
public MenuItemSamplePage()
{
this.InitializeComponent();
var command = new DelegateCommand<object>(Click, CanExecute);
this.DataContext = command;
}
private void Click(object parameter)
{
MessageDialog dialog = new MessageDialog(parameter.ToString());
dialog.ShowAsync();
}
private bool CanExecute(object parameter)
{
string text = parameter as string;
return string.IsNullOrWhiteSpace(text) == false;
}
这里用到的DelegateCommand也是UWPCommunityToolkit中的类 :DelegateCommand
[UWP 自定义控件]了解模板化控件(7):支持Command的更多相关文章
- UWP 自定义控件:了解模板化控件 系列文章
UWP自定义控件的入门文章 [UWP 自定义控件]了解模板化控件(1):基础知识 [UWP 自定义控件]了解模板化控件(2):模仿ContentControl [UWP 自定义控件]了解模板化控件(2 ...
- [UWP 自定义控件]了解模板化控件(8):ItemsControl
1. 模仿ItemsControl 顾名思义,ItemsControl是展示一组数据的控件,它是UWP UI系统中最重要的控件之一,和展示单一数据的ContentControl构成了UWP UI的绝大 ...
- [UWP 自定义控件]了解模板化控件(10):原则与技巧
1. 原则 推荐以符合以下原则的方式编写模板化控件: 选择合适的父类:选择合适的父类可以节省大量的工作,从UWP自带的控件中选择父类是最安全的做法,通常的选择是Control.ContentContr ...
- [UWP 自定义控件]了解模板化控件(1):基础知识
1.概述 UWP允许开发者通过两种方式创建自定义的控件:UserControl和TemplatedControl(模板化控件).这个主题主要讲述如何创建和理解模板化控件,目标是能理解模板化控件常见的知 ...
- [UWP 自定义控件]了解模板化控件(2):模仿ContentControl
ContentControl是最简单的TemplatedControl,而且它在UWP出场频率很高.ContentControl和Panel是VisualTree的基础,可以说几乎所有VisualTr ...
- [UWP 自定义控件]了解模板化控件(2.1):理解ContentControl
UWP的UI主要由布局容器和内容控件(ContentControl)组成.布局容器是指Grid.StackPanel等继承自Panel,可以拥有多个子元素的类.与此相对,ContentControl则 ...
- [UWP 自定义控件]了解模板化控件(3):实现HeaderedContentControl
1. 概述 来看看这段XMAL: <StackPanel Width="300"> <TextBox Header="TextBox" /&g ...
- [UWP 自定义控件]了解模板化控件(4):TemplatePart
1. TemplatePart TemplatePart(部件)是指ControlTemplate中的命名元素.控件逻辑预期这些部分存在于ControlTemplate中,并且使用protected ...
- [UWP 自定义控件]了解模板化控件(5.2):UserControl vs. TemplatedControl
1. UserControl vs. TemplatedControl 在UWP中自定义控件常常会遇到这个问题:使用UserControl还是TemplatedControl来自定义控件. 1.1 使 ...
随机推荐
- 安装Linux Mint 17后要做的20件事
Linux Mint 17 Qiana Cinnamon Linux Mint 17已经发布,定名为Qiana.Mint是Linux最佳发行版之一,它定位于桌面用户,关注可用性和简洁.它携带了风格迥异 ...
- C# MD5 加密
public static string MD5Encrypt(string clearText) { string result = string.Empty; byte[] byteArray = ...
- SQLSERVER 死锁
select request_session_id spid, OBJECT_NAME(resource_associated_entity_id) tableName from sys.dm_tra ...
- VSCode + PYQT5 + QtDesigner 环境搭建和测试
目的:编写Python桌面应用程序. 备注:也可以选择VS2017+QtDesigner ,但更喜欢VSCode 第1步:安装PyQt5和PyQt5-tools pip3 install -i htt ...
- Eclipse配置和使用Maven
一.ecplise配置Maven 1.下载eclipse的Maven插件.(有些eclipse版本中已经集成了此Maven插件,可以不用下载). 需要下载m2eclipse插件. 2.安装m2ecli ...
- 实验吧web题(26/26)全writeup!超详细:)
#简单的SQL注入 http://www.shiyanbar.com/ctf/1875 1)试着在?id=1,没有错误 2)试着?id=1',出错了,有回显,说明有注入点: You have an e ...
- 4.3Python数据类型(3)之字符串类型
返回总目录 目录: 1.字符串的概念 2.字符串的形式 3.字符串的转义符 4.字符串一般操作 5.字符串函数操作 (一)字符串的概念 由单个字符组成的一个集合 (二)字符串的形式 双引号与单引号的效 ...
- 自己动手写waf指纹识别
import requests import re def target_url(scan_url): xssstring = '<script>alert(1)</script&g ...
- ccf-20170303--Markdown
我的想法如下图: 代码和题目如下: 问题描述 试题编号: 201703-3 试题名称: Markdown 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 Markdown 是一 ...
- 【学习笔记】cache/buffer
cache 是为了弥补高速设备和低速设备的鸿沟而引入的中间层,最终起到**加快访问速度**的作用.buffer 的主要目的进行流量整形,把突发的大数量较小规模的 I/O 整理成平稳的小数量较大规模的 ...