[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 使 ...
随机推荐
- CSS3创建圆圈进度条
最近在工作中需要做一个圆圈倒计时,刚开始的想法是做个纯数字的倒计时即可,可是需求觉得这个不太好看,想加个倒计时进度条.于是就有了接下来的分析过程... 我们知道CSS3可以很方便的画圆,圆环,然后在加 ...
- List基础操作
/** * List基础操作 * Created by zhen on 2018/11/14. */ object ListDemo { def main(args: Array[String]) { ...
- centos 7.2 64位 docker安装lamp环境
1. 删除docker可能有的早期版本 yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docke ...
- CSS| 學習心得
resize :both , 只有overflow設置為auto時, 才能起作用???
- [SequenceFile_1] Hadoop 序列文件
1. 关于 SequenceFile 对于日志文件来说,纯文本不适合记录二进制类型数据,通过 SequenceFile 为二进制键值对提供了持久的数据结构,将其作为日志文件的存储格式时,可自定义键(L ...
- Kubernetes的搭建与配置(一):集群环境搭建
1.环境介绍及准备: 1.1 物理机操作系统 物理机操作系统采用Centos7.3 64位,细节如下. [root@localhost ~]# uname -a Linux localhost.loc ...
- 【PAT】B1076 Wifi密码(15 分)
注意接收字符时缓冲区的换行要接受掉 #include<stdio.h> int main() { int n; scanf("%d", &n); n *= 4; ...
- python3的C3算法
一.基本概念 1. mro序列 MRO是一个有序列表L,在类被创建时就计算出来. 通用计算公式为: mro(Child(Base1,Base2)) = [ Child ] + merge( mro(B ...
- pThreads线程(一) 基本API
1.创建线程 int pthread_create(pthread_t *restrict_ptid, const pthread_attr_t *restrict_att ...
- 环境搭建-----IntelliJ idea之resin配置
目前网上的相关资料太少了 自己只能摸索着尝试 最后在领导的帮忙下 成功实现了环境的集成 网上查到的一般都是修改resin的配置文件等等 其实完全没有必要 本人之前在intellij下部署resin遇到 ...