zoukankan      html  css  js  c++  java
  • [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

  • 相关阅读:
    Delphi / C++ Builder 使用 UDT ( UDP-based Data Transfer ) 4.11
    STUN: NAT 类型检测方法
    udt nat traverse
    UDT: Breaking the Data Transfer Bottleneck
    Freescale OSBDM JM60仿真器
    How To: Perl TCP / UDP Socket Programming using IO::Socket::INET
    NAT类型与穿透 及 STUN TURN 协议
    根据PID和VID得到USB转串口的串口号
    pic/at89c2051 programmer
    IC开短路测试(open_short_test),编程器测试接触不良、开短路
  • 原文地址:https://www.cnblogs.com/dino623/p/TemplatedControlWithCommand.html
Copyright © 2011-2022 走看看