WPF自定義命令


  在實際的編程工作中,我們可以只是用事件,不用命令,程序的邏輯也一樣被驅動的很好,但我們不能阻止程序員按照自己的習慣去寫代碼。比如保存事件的處理器,程序員們可以寫Save()、Savehandler()、SaveDocument()...這些都符合代碼規范,但是遲早有一天整個項目會變得無法讀懂,新來的程序員或者修改bug的程序員會很抓狂。

WPF命令簡介       

WPF的命令是實現了ICommand接口的類。ICommand接口非常簡單,只包含兩個方法和一個事件。

  • Execute方法:命令執行,或者說命令作用於目標之上。
  • CanExecute方法:在執行之前來彈指命令是否可被執行。
  • CanExecuteChanged事件:當命令執行狀態發生改變時,可激發此事件來通知其他對象。

RoutedCommand就是這樣一個實現了ICommand接口的類。RoutedCommand在實現ICommand接口時,並未向其中添加任何邏輯。

WPF的命令系統由幾個基本元素構成,他們是:

  • 命令:WPF命令實際上就是實現了ICommand接口的類,平時使用最多的是RoutedCommand類。
  • 命令源:即命令的發送者,是實現了ICommandSource接口的類。
  • 命令目標:即命令將推送給誰,或者說命令將作用在誰身上。命令目標是必須實現了IInputElement接口的類。
  • 命令關聯:負責把一些外圍邏輯與命令關聯起來,比如執行之前對命令是否可執行進行判斷、命令執行后還有那些后續工作等。

 命令具有一處聲明處處可用的特點,因此,MS在WPF類庫里准備而來一些便捷的命令庫,例如:

下面分別用WPF命令庫,和自定義命令實現同樣的功能。

WPF命令庫命令   

Demo程序的UI如下:

<Window x:Class="WPFCommand.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">
    <Window.CommandBindings>
        <CommandBinding Command="New" CanExecute="CommandBinding_CanExecute" Executed="CommandBinding_Executed"/>
    </Window.CommandBindings>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <DockPanel Height="60" Grid.Row="0">
            <TextBlock VerticalAlignment="Center"  Text="Name:" DockPanel.Dock="Left"  Width="100" FontSize="30" Foreground="PaleVioletRed"/>
            <TextBox x:Name="txtName" DockPanel.Dock="Right"  FontSize="40"/>
        </DockPanel>
        <Button Command="New" CommandParameter="Teacher" Content="New Teacher" Grid.Row ="1"/>
        <Button Command="New" CommandParameter="Student" Content="New Student" Grid.Row ="2"/>
        <ListBox x:Name="listBox1" Grid.Row="3" Grid.RowSpan="2"/>
    </Grid>
</Window>

后台代碼如下:

using System.Windows;
using System.Windows.Input;

namespace WPFCommand
{
    /// <summary>
    /// MainWindow.xaml 的交互邏輯
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if (string.IsNullOrWhiteSpace(txtName.Text))
            {
                e.CanExecute = false;
            }
            else
            {
                e.CanExecute = true;
            }
        }

        private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            string name = txtName.Text;
            if (e.Parameter.ToString() == "Teacher")
            {
                listBox1.Items.Add("New Teacher: "+name);
            }
            if (e.Parameter.ToString() == "Student")
            {
                listBox1.Items.Add("New Student: "+name);
            }
        }
    }
}

程序的運行結果如下:

當txtName.Text為WhiteSpace時,命令不可被執行。

執行后效果如下:

前面說過不用命令,程序的邏輯也可以被驅動的很好。且在一般情況下,在程序中使用與邏輯無關的RoutedCommand來跑跑龍套也就足夠了,上面這個命令用的就有十足的“醬油”的嫌疑。

 OK,把打醬油進行到底吧,下面自定義一個命令,實現相同的功能。

WPF自定義命令    

注意對比前面使用命令庫命令的方法異同。

程序的UI如下:

<Window x:Class="MyCommand.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="My Command Window" Height="350" Width="525" x:Name="mainWindow" >
    <Grid >
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <DockPanel Height="60" Grid.Row="0">
            <TextBlock VerticalAlignment="Center"  Text="Name:" DockPanel.Dock="Left"  Width="100" FontSize="30" Foreground="PaleVioletRed"/>
            <TextBox x:Name="txtName" DockPanel.Dock="Right"  FontSize="40"/>
        </DockPanel>
        <Button  CommandParameter="Teacher"  x:Name="button1" Content="New Teacher" Grid.Row ="1"/>
        <Button  CommandParameter="Student"  x:Name="button2" Content="New Student" Grid.Row ="2"/>
        <ListBox x:Name="listBox1" Grid.Row="3" Grid.RowSpan="2"/>
    </Grid>
</Window>

后台代碼如下:

using System.Windows;
using System.Windows.Input;

namespace MyCommand
{
    /// <summary>
    /// MainWindow.xaml 的交互邏輯
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            //
            InitCmd();
        }

        //聲明並定義命令
        private RoutedCommand newCmd=new RoutedCommand ("NewTS",typeof(MainWindow ));

        private void InitCmd()
        {            
            //創建命令關聯
            CommandBinding cb = new CommandBinding();
            cb.Command = newCmd;
            cb.CanExecute += new CanExecuteRoutedEventHandler(CanExecute1);
            cb.Executed += new ExecutedRoutedEventHandler(Executed1);
            //把命令關聯安置在外圍控件上
            mainWindow.CommandBindings.Add(cb);

            //把命令賦值給命令源(發送者)
            button1.Command = newCmd;
            button2.Command = newCmd;
        }

        private void CanExecute1(object sender,CanExecuteRoutedEventArgs e)
        {
            //e.CanExecute = true;
            if (string.IsNullOrWhiteSpace(txtName.Text))
            {
                e.CanExecute = false;
            }
            else
            {
                e.CanExecute = true;
            }
        }

        private void Executed1(object sender, ExecutedRoutedEventArgs e)
        {
            string name = txtName.Text;
            if (e.Parameter.ToString() == "Teacher")
            {
                listBox1.Items.Add("New Teacher: " + name);
            }
            if (e.Parameter.ToString() == "Student")
            {
                listBox1.Items.Add("New Student: " + name);
            }
        }
    }
}

程序的運行效果和上面的相同: 

當txtName.Text為WhiteSpace時,命令不可被執行。

執行后效果如下:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM