欢迎莅临 SUN WU GANG 的园子!!!

世上无难事,只畏有心人。有心之人,即立志之坚午也,志坚则不畏事之不成。

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  470 随笔 :: 0 文章 :: 22 评论 :: 30万 阅读
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

命令系统的基本元素和关系
WPF命令系统的组成要素:
A.命令(command):WPF命令实际上就是实习了ICommand接口的类。平时使用最多的就是RoutedCommand类。
B.命令源(command source):即命令的发送者,实现了ICommandSource接口的类。
C.命令目标(command Target):即命令发给了谁或理解为命令的接收者。命令目标必须是实现了IInputElement接口的类。
D.命令关联(command Binding):负责把一些外围逻辑和命令关联起来。比如执行之前对命令是否可以执行进行判、命令执行之后还有哪些后续工作等。

命令使用的步骤:
1.创建命令类
2.声明命名实例
3.指定命令源
4.指定命令目标
5.设置命令关联

ICommand接口与RoutedCommand
WPF中的命令是实现了ICommand接口的类。
ICommand接口非常简单,只包含两个方法一个事件。
<1>Execute方法:命令执行,或者说命令执行于命令目标之上。需要注意的是,现实世界中的命令是不会自己执行的,而这里,执行变成了命令的方法,有点拟人化的味道。
<2>CanExecute方法:在执行之前探知命令是否可以执行。
<3>CanExecuteChanged事件:当命令的可执行状态改变的时候,可激发此事件通知其它对象。

RoutedCommand就是一个实现了ICommand接口的类。
RoutedCommand在实现ICommand接口时,并未向Execute和CanExecute方法中添加任何逻辑,
也就是说,它是通用的、与具体的业务逻辑无关的。

 

复制代码
<Window x:Class="命令1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel Background="Red" x:Name="sp1">
        <Button x:Name="btn1" Content="Send Clear Command" Margin="5" Background="{Binding}"/>
        <TextBox x:Name="txtA" Margin="5,0" Height="200"/>
    </StackPanel>
</Window>
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
using System.Windows;
using System.Windows.Input;
 
namespace 命令1
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
 
            InitializeCommand();
        }
 
        //1.创建命令类
        //2.声明命名实例
        //3.指定命令源—— 命令发送者
        //4.指定命令目标——命令接收者
        //5.设置命令关联
 
        //声明并定义命令  
        private RoutedCommand RouutedCommand = new RoutedCommand("可输入非空字符", typeof(MainWindow));
 
        private void InitializeCommand()
        {
            //把命令赋值给命令源,并定义快捷键  
            this.btn1.Command = RouutedCommand;
            this.RouutedCommand.InputGestures.Add(new KeyGesture(Key.C, ModifierKeys.Alt));
            //指定命令目标  
            this.btn1.CommandTarget = txtA;
 
            //创建命令关联  
            CommandBinding commandBinding = new CommandBinding();
            commandBinding.Command = RouutedCommand;//只关注与rouutedCommand相关的命令
            commandBinding.CanExecute += new CanExecuteRoutedEventHandler(cb_CanExecute);
            commandBinding.Executed += new ExecutedRoutedEventHandler(cb_Execute);
            //把命令关联安置在外围控件上  
            this.sp1.CommandBindings.Add(commandBinding);
        }
 
        //当命令到达目标之后,此方法被调用  
        private void cb_Execute(object sender, ExecutedRoutedEventArgs e)
        {
            this.txtA.Clear();
            //避免事件继续向上传递而降低程序性能  
            e.Handled = true;
        }
 
        //当探测命令是否可执行的时候该方法会被调用  
        private void cb_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if (string.IsNullOrEmpty(txtA.Text))
            {
                e.CanExecute = false;
            }
            else
            {
                e.CanExecute = true;
            }
            //避免事件继续向上传递而降低程序性能  
            e.Handled = true;
        }
    }
}
 
//对于以上的代码,需要注意以下几点:
//第一,使用命令可以避免自己写代码判断Button是否可以用以及添加快捷键。
 
//第二,RountedCommand是一个与业务逻辑无关的类,只负责在程序中跑腿而并不对命令目标进行操作,
//TextBox并不是由它清空的。那么TextBox的情况操作是谁呢?答案是CommandBinding。
//因为无论是探测命令是否可以执行还是命令送达目标,都会激发命令目标发送路由事件,
//这些事件会沿着UI元素树向上传递,最终被CommandBinding所捕捉。
//本例中CommandBinding被安装在外围的StackPanel上,Commandbinding站在高处起一个侦听器的作用,
//而且专门针对rouutedCommand命令捕捉与其相关的事件。
//本例中,当CommandBinding捕捉到CanExecute就会调用cb_CanExecute方法。
//当捕捉到是Executed的时候,就调用cb_Execute事件。
 
//第三,因为CanExecute事件的激发频率比较高,为了避免降低性能,在处理完毕之后建议将e.Handle设置为true。
//第四,CommandBinding一定要设置在命令目标的外围控件上,不然无法捕捉CanExecute和Executed等路由事件。

 

实例二:

复制代码
<Window x:Class="命令2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="24" />
            <RowDefinition Height="4" />
            <RowDefinition Height="24" />
            <RowDefinition Height="4" />
            <RowDefinition Height="24" />
            <RowDefinition Height="4" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        
        <!--命令和命令参数-->
        <TextBlock  HorizontalAlignment="Left" Name="textBlock1" Text="Name:" VerticalAlignment="Center" Grid.Row="0"/>
        <TextBox x:Name="txtName" Margin="60,5,0,0" Grid.Row="0"/>
        <Button Content="New Teacher" Grid.Row="2" Command="New" CommandParameter="Teacher"/>
        <Button Content="New Student" Grid.Row="4" Command="New" CommandParameter="Student"/>
        <ListBox Grid.Row="6" x:Name="lbInfos"/>
    </Grid>
    
    <!--为窗体添加CommandBinding-->
    <Window.CommandBindings>
        <CommandBinding Command="New" CanExecute="CommandBinding_CanExecute" Executed="CommandBinding_Executed"/>
    </Window.CommandBindings>
</Window>
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
using System.Windows;
using System.Windows.Input;
 
namespace 命令2
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        //两个按钮都使用的是New命令,但分别使用的是Student和Teacher做为的参数。
 
        public MainWindow()
        {
            InitializeComponent();
        }
 
        /// <summary>
        /// 当探测命令是否可执行的时候该方法会被调用
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if (string.IsNullOrEmpty(txtName.Text))
            {
                e.CanExecute = false;
            }
            else
            {
                e.CanExecute = true;
            }
            //路由终止,提高系统性能  
            e.Handled = true;
        }
 
        /// <summary>
        /// 当命令到达目标之后,此方法被调用  
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            if (e.Parameter.ToString() == "Student")
            {
                this.lbInfos.Items.Add(string.Format("New Student:{0} 好好学习,天天向上。", txtName.Text));
            }
            else if (e.Parameter.ToString() == "Teacher")
            {
                this.lbInfos.Items.Add(string.Format("New Teacher:{0} 学而不厌,诲人不倦。", txtName.Text));
            }
            //路由终止,提高系统性能  
            e.Handled = true;
        
    }
}

 

实例三:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace 命令4
{
    public interface IView
    {
        //属性  
        bool IsChanged { get; set; }
        //方法  
        void SetBinding();
        void Refresh();
        void Clear();
        void Save();
    }
}
 
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
 
namespace 命令4
{
    public class ClearCommand : ICommand
    {
        //当命令可执行状态发送改变时,应当被激发  
        public event EventHandler CanExecuteChanged;
 
        //用来判断命令是否可以执行  
        public bool CanExecute(object parameter)
        {
            throw new NotImplementedException();
        }
 
        //命令执行时,带有与业务相关的Clear逻辑  
        public void Execute(object parameter)
        {
            IView view = parameter as IView;
            if (view != null)
            {
                view.Clear();
            }
        }
    }
}
 
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows;
 
namespace 命令4
{
    public class MyCommandSource : UserControl, ICommandSource
    {
        /// <summary>  
        /// 继承自ICommand的3个属性  
        /// </summary>  
        public ICommand Command
        {
            get;
            set;
        }
 
        public object CommandParameter
        {
            get;
            set;
        }
 
        public IInputElement CommandTarget
        {
            get;
            set;
        }
 
        //在命令目标上执行命令,或者说让命令作用于命令目标  
        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            base.OnMouseLeftButtonDown(e);
            if (this.CommandTarget != null)
            {
                this.Command.Execute(CommandTarget);
            }
        }
    }
}
复制代码
<UserControl x:Class="命令4.UCMniView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Border CornerRadius="5" BorderBrush="GreenYellow" BorderThickness="2">
        <StackPanel>
            <TextBox Margin="5" x:Name="txt1"></TextBox>
            <TextBox Margin="5" x:Name="txt2"></TextBox>
            <TextBox Margin="5" x:Name="txt3"></TextBox>
            <TextBox Margin="5" x:Name="txt4"></TextBox>
        </StackPanel>
    </Border>

</UserControl>
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
using System;
using System.Windows.Controls;
 
namespace 命令4
{
    /// <summary>
    /// UserControl.xaml 的交互逻辑
    /// </summary>
    public partial class UCMniView : UserControl,IView
    {
        public UCMniView()
        {
            InitializeComponent();
        }
 
        public bool IsChanged
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }
 
        public void SetBinding()
        {
            throw new NotImplementedException();
        }
 
        public void Refresh()
        {
            throw new NotImplementedException();
        }
 
        public void Clear()
        {
            this.txt1.Clear();
            this.txt2.Clear();
            this.txt3.Clear();
            this.txt4.Clear();
        }
 
        public void Save()
        {
            throw new NotImplementedException();
        }
    }
}
复制代码
<Window x:Class="命令4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:命令4"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <local:MyCommandSource x:Name="myCommandSource1">
            <TextBlock Text="清除" Width="80" FontSize="16" TextAlignment="Center" Background="LightGreen"/>
        </local:MyCommandSource>

        <local:UCMniView x:Name="mniView1" />
    </StackPanel>

</Window>
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
 
namespace 命令4
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
 
            ClearCommand clearCommand = new ClearCommand();
            this.myCommandSource1.Command = clearCommand;
            this.myCommandSource1.CommandTarget = mniView1; 
        }
    }
}

 

posted on   sunwugang  阅读(364)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
点击右上角即可分享
微信分享提示