zoukankan      html  css  js  c++  java
  • 【WPF】命令系统

    引言

         在MVVM模式开发下,命令Command是编程中不可或缺的一部分.下面,我分3种场景简单介绍一下命令的用法.

    ViewModel中的命令

         在ViewModel定义命令是最常用的用法,开发中几乎90%以上的命令都在用在ViewModel上.怎么用?先从实现ICommand说起,下面定义一个命令

        public class MyCommand :ICommand
        {
            public bool CanExecute(object parameter)
            {
                return true;
            }
            public event EventHandler CanExecuteChanged;
    
            public void Execute(object parameter)
            {
                MessageBox.Show("命令已经执行!");
            }
        }

    然后在ViewModel中定义一个命令,赋值MyCommand,接着在View绑定命令,如下

        public class MainWindowViewModel
        {
            public MainWindowViewModel()
            {
                myCommand = new MyCommand();
            }
            public ICommand myCommand {get ; set ; }
    
        }
    <Window x:Class="WpfCommand.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:WpfCommand"
            Title="MainWindow" Height="350" Width="525">
        <Grid>      
            <Button Command="{Binding myCommand}"  Name="btn"  Height="30" Width="80" Margin="104,75,0,0" VerticalAlignment="Top" HorizontalAlignment="Left">执行命令</Button>
        </Grid>
    </Window>

    上面看起来不复杂,但是实际开发绝对不这么干的,如果每个命令都要自定义类,还能好好玩耍么.实际开发,我们可以借助第三方类轻松完成我们的命令实现,如Prism框架的DelegateCommand,MVVMLight的RelayCommand,下面演示一下DelegateCommand,只需在ViewModel中实例化一个命令既可.

     public class MainWindowViewModel
        {
            public MainWindowViewModel()
            {
                myCommand = new DelegateCommand(() => { MessageBox.Show("命令已经执行!"); }, () => true); 
            }
            public ICommand myCommand {get ; set ; }
        }

     自定义控件中的命令绑定

          在自定义控件中绑定命令不常见,但是某些场景下还是有用的.例如DataGrid的新增行,删除行,绑定自定义命令,让外部调用还是很有用的.下面,用继承TextBox做个演示吧.

          利用CommandManager绑定命令,命令的作用是将字体变成红色,无文本时则命令不可用.MyTextBox定义如下

    public  class MyTextBox:TextBox
        {
    
          static MyTextBox()
          {
              CommandManager.RegisterClassCommandBinding(typeof(MyTextBox),
                      new CommandBinding(MyCommands.MyRoutedCommand,
                      Command_Executed, Command_CanExecute));       
          }
    
          private static void Command_CanExecute(object sender, CanExecuteRoutedEventArgs e)
          {
              MyTextBox myTextBox = (MyTextBox)sender;
              e.CanExecute = !string.IsNullOrWhiteSpace(myTextBox.Text);  
          }
          private static void Command_Executed(object sender, ExecutedRoutedEventArgs e)
          {
              MyTextBox myTextBox = (MyTextBox)sender;
              myTextBox.Foreground = new SolidColorBrush(Colors.Red);
          }
        }
     public class MyCommands
       {
           private static RoutedUICommand myRoutedCommand;
           static MyCommands()
           {
               myRoutedCommand = new RoutedUICommand(
                 "MyRoutedCommand", "MyRoutedCommand", typeof(MyCommands));
           }
           public static RoutedUICommand MyRoutedCommand
           {
               get { return myRoutedCommand; }
           }
       }

    如何使用,很简单,设置一下Button的Command和CommandTarget即可,如下

    <Window x:Class="WpfCommand.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:WpfCommand"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <local:MyTextBox  x:Name="mytextbox"></local:MyTextBox>
            <Button Command="local:MyCommands.MyRoutedCommand"  CommandTarget="{Binding ElementName=mytextbox}"  Name="btn"  Height="30" Width="80" Margin="104,75,0,0" VerticalAlignment="Top" HorizontalAlignment="Left">执行命令</Button> </Grid> </Window>

    自定义控件中的命令属性

           在WPF的控件库,我们会发现很多控件都带有Command,例如Button.控件中有Command属性才能让我们如期望地执行命令.如果我们的自定义控件想定义这个Command,就要实现ICommandSource了.下面从定义一个简单按钮来演示一下.

    public class MyButton : ContentControl,ICommandSource
        {
            public static readonly DependencyProperty CommandProperty =
                DependencyProperty.Register(
                    "Command",
                    typeof(ICommand),
                    typeof(MyButton),
                    new PropertyMetadata((ICommand)null,
                    new PropertyChangedCallback(CommandChanged)));
    
            public ICommand Command
            {
                get
                {
                    return (ICommand)GetValue(CommandProperty);
                }
                set
                {
                    SetValue(CommandProperty, value);
                }
            }
      
            public static readonly DependencyProperty CommandTargetProperty =
                DependencyProperty.Register(
                    "CommandTarget",
                    typeof(IInputElement),
                    typeof(MyButton),
                    new PropertyMetadata((IInputElement)null));
    
            public IInputElement CommandTarget
            {
                get
                {
                    return (IInputElement)GetValue(CommandTargetProperty);
                }
                set
                {
                    SetValue(CommandTargetProperty, value);
                }
            }
    
           
            public static readonly DependencyProperty CommandParameterProperty =
                DependencyProperty.Register(
                    "CommandParameter",
                    typeof(object),
                    typeof(MyButton),
                    new PropertyMetadata((object)null));
    
            public object CommandParameter
            {
                get
                {
                    return (object)GetValue(CommandParameterProperty);
                }
                set
                {
                    SetValue(CommandParameterProperty, value);
                }
            }
    
            private static void CommandChanged(DependencyObject d,
               DependencyPropertyChangedEventArgs e)
            {
    
            }
            //在鼠标的按下事件中,调用命令的执行
            protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
            {
                base.OnMouseLeftButtonDown(e);
    
                if (!Command.CanExecute(CommandParameter))
                    return;
                Command.Execute(CommandParameter);
            }
        }

    上面只是简单地定义了命令,实际上Button的Command定义要比上面复杂些,有兴趣的童鞋可以去看看Button的源码,推荐一款反编译神器dotPeek.下面是Xaml的定义.

    <Window x:Class="WpfCommand.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:WpfCommand"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <local:MyTextBox  x:Name="mytextbox"></local:MyTextBox>
            <local:MyButton Height="50" Width="80" Command="local:MyCommands.MyRoutedCommand"  CommandTarget="{Binding ElementName=mytextbox}" >
                <Ellipse Fill="Blue">
                </Ellipse>
            </local:MyButton>
        </Grid>
    </Window>

     小结

         本着从实际出发的原则,命令的介绍和其他内容被我省略了.最后,如果你有更好的想法,请不吝留言指教.

          

  • 相关阅读:
    数据库之ORACLE常见基础操作
    数据库基础之Oracle函数
    Snuketoon [ABC217H]
    Cards [CF1278F]
    Squirrel Migration [ARC087F]
    Xor Query [ABC223H]
    Three Permutations [ABC214G]
    雨林跳跃[APIO2021]
    Redis5.0 主从模式和高可用 搭建和测试报告
    Redis5 压力测试结果反馈报告
  • 原文地址:https://www.cnblogs.com/caizl/p/4557417.html
Copyright © 2011-2022 走看看