[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 自定义控件]了解模板化控件(7):支持Command
以我的经验来说,要让TemplatedControl支持Command的需求不会很多,大部分情况用附加属性解决这个需求会更便利些,譬如UWPCommunityToolkit的HyperlinkExte ...
- 【UWP】使用Action代替Command
在Xaml中,说到绑定,我们用的最多的应该就是ICommand了,通过Command实现ViewModel到View之间的命令处理,例如Button默认就提供了Command支持,如下 Xaml: & ...
- [UWP]了解模板化控件(8):ItemsControl
1. 模仿ItemsControl 顾名思义,ItemsControl是展示一组数据的控件,它是UWP UI系统中最重要的控件之一,和展示单一数据的ContentControl构成了UWP UI的绝大 ...
- Win10商店东方财富网 UWP版更新,支持平板,PC,手机
东方财富股份有限公司 近日向Win10商店提交了东方财富网V4.1版,这次为广大Win10平台用户带来了期待已久的桌面版本,可谓是良心厂商,值得鼓励和支持.4.1主要更新: 1. 支持桌面Window ...
- Win10 UWP 开发系列:支持异步的SQLite
上篇文章已经实现了在UWP中使用SQLite作为本地存储,作为移动端的程序,及时响应用户的操作是提高用户体验的重要途径,因此UWP的很多api都是异步的.那么如何使SQLite支持异步呢? 参考SQL ...
- [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]了解模板化控件(4):TemplatePart
1. TemplatePart TemplatePart(部件)是指ControlTemplate中的命名元素.控件逻辑预期这些部分存在于ControlTemplate中,并且使用protected ...
随机推荐
- SQL中锁表语句简单理解(针对于一个表)
锁定数据库的一个表 复制代码代码如下: SELECT * FROM table WITH (HOLDLOCK) 注意: 锁定数据库的一个表的区别 复制代码代码如下: SELECT * FROM tab ...
- java 虚拟机的类加载机制
Java 虚拟机的类加载机制 关于类加载机制: 虚拟机把描述类的数据从Class 文件加载到内存,并对数据进行效验.转换解析和初始化,最终 形成可以被虚拟机直接使用的Java 类型,就是虚拟机的类 ...
- MySQL GTIDs(global transaction identifiers)
1.如何定义和生成GTIDs 唯一性:在所有主从库都是唯一的,由二元组构成 每个事务和GTIDs之间都有1:1映射 GTID = source_id:transaction_id source_id标 ...
- web工程自动部署(tomcat服务器)
工作中经常需要把web项目打成war包之后部署到tomcat服务器上,每次更新时步骤比较类似,这里提供公共步骤,编写名为auto_deploy.sh的shell脚本,只需要传递两个参数即可自动完成部署 ...
- "虐待"过我的老师们,你们如今还好吗
当皇城脚下的民生问题都这么难做的时候,其他地方又该如何保障呢? 京城“红黄蓝”出名了,京城发生锅炉大爆炸了,京城发生火灾了…… 聊天中,有一好友突然蹦出了一句话:“你看在皇城脚下都不安全了”. 久久我 ...
- 负载均衡手段之DNS轮询
大多数域名注册商都支持对统一主机添加多条A记录,这就是DNS轮询,DNS服务器将解析请求按照A记录的顺序,随机分配到不同的IP上,这样就完成了简单的负载均衡.下图的例子是:有3台联通服务器.3台电信服 ...
- RecyclerView.ItemDecoration
decoration 英文意思: 英[ˌdekəˈreɪʃn] 美[ˌdɛkəˈreʃən] n. 装饰品; 装饰,装潢; 装饰图案,装饰风格; 奖章; [例句]The decoration and ...
- 通用Adapter设计,SparseArray+泛型+回调的使用
看到题目,我相信聪明的各位已经有一定想法了. 一个Adapter,最简单的优化就是使用泛型,他可以省去非常多的代码,不过在此之上,我们还可以继续优化,优化他的好基友是:ViewHolder. 在过去, ...
- put()
put() 作用: 将集合的所有键名和值,存放在一个集合对象中. public Map selectSingleData(String sql,Object...obj) throws SQLExc ...
- 虚拟机安装 deepin Linux 注意事项
主要要注意下面几点: 一.虚拟机"客户机操作系统"类型 选择"Windows 7 x64" 选择"客户机操作系统"类型,这个选择十分重要,D ...