[UWP]了解模板化控件(7):支持Command

2017-05-01 20:45:57来源:cnblogs.com作者:dino.c人点击

以我的经验来说,要让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

最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台