程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> WPF命令介紹、命令和數據綁定集成應用

WPF命令介紹、命令和數據綁定集成應用

編輯:關於.NET

要開始使用命令,必須做三件事:

一:定義一個命令

二:定義命令的實現

三:為命令創建一個觸發器

WPF中命令系統的基礎是一個相對簡單的ICommand的接口,代碼如下:

public interface ICommand 
{
 event EventHandler CanExecuteChanged;
 bool CanExecute(object parameter);
 void Execute(object parameter); 
}

CanExecute用於確定命令是否處於可執行的狀態。典型的,UI控件能使用CanExecute來啟用或禁用 自己。也就是說,在相關的命令從CanExecute中返回False的時候,按鈕將變得不可用。

Execute是命 令的關鍵,當被調用時,它將觸發命令的執行。

要定義一個新命令,可以實現ICommand接口。如希望ICommand在被調用後關閉應用程序,代碼如下:

public class Exit : ICommand {
 event EventHandler CanExecuteChanged;
 public bool CanExecute(object parameter) 
{
 return true; 
} 
public void Execute(object parameter)
 { 
Application.Current.Shutdown(); 
} 
}

要把一個菜單項綁定到應用程序關閉這個命令上,可以把他們的Command屬性掛到Exit命令上,代 碼如下:

<MenuItem Header="_File">
 <MenuItem Header="_Exit">
 <MenuItem.Command>
 <local:Exit/> 
</MenuItem.Command>
 </MenuItem> 
</MenuItem>

由於把命令用於多個位置比較常見,所以創建一個存儲命令的靜態字段也常見:

public static readonly ICommand ExitCommand = new Exit();

這樣做的好處是,通過 這個類型為ICommand的字段,可以讓Exit命令的實現完全私有化。現在,可以把Exit標記為私有類,並把標記 轉化為綁定到靜態字段,代碼如下:

<MenuItem Header="_File">
            <MenuItem Header="_Exit" Command="{x:Static local:WinCommand.ExitCommand}"/>
        </MenuItem>

下面我們通過添加一個和Close命令掛接的按鈕,可以為窗口編寫一個 模板,以實現關閉窗口的功能,代碼如下:

<Window.Style>
        <Style TargetType="Window">
    
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate  TargetType="Window">
                        <DockPanel>
                            <StatusBar DockPanel.Dock="Bottom">
                                <StatusBarItem>
                                    <Button 
                            Command="{x:Static 

ApplicationCommands.Close}">Close</Button>
                                </StatusBarItem>
                            </StatusBar>
                            <ContentPresenter/>
                        </DockPanel>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Style>

我們接著要通過把命令綁定添加到窗口中讓窗口關閉。

/// 

<summary>
    /// WinCommand.xaml 的交互邏輯
    /// </summary>
    public partial class WinCommand : Window
    {
        public static readonly ICommand ExitCommand = new Exit();
        public WinCommand()
        {
            InitializeComponent();
    
            CommandBindings.Add(
                new CommandBinding(
                    ApplicationCommands.Close,
                    CloseExecuted));
    
        }
    
        void CloseExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            this.Close();
        }
          
    }

使用命令可以清晰地把顯示和行為分開。通過使用單一的名稱為所需的語義動作簽名,在嘗試 把多個控件和單個事件處理過程掛接起來的時候,可以避免很多由此引發的緊耦合問題。通常,應用程序邏輯 應該總是通過命令的方式來實現的,而不是事件處理程序。對於很多需要直接掛接到事件處理過程上的常見例 子,用觸發器來處理更好。

命令與數據綁定

使用命令的一個令人振奮和強大的特性 就是和 數據綁定集成。由於Command和CommandParameter都是元素上的屬性,所以他們都能被設置為一些綁定到他們 的數據。因此,可以使用綁定的數據內容來確定應該發生的動作。

為了演示他們是如何融合到一起的,將以C:\下面的文件的應用程序來開頭。首先,定義一個顯示內 容的ListBox,和一個顯示了每個文件名的數據模板,代碼如下:

<ListBoxMargin="2"Name="lbFile">

<ListBox.ItemTemplate>

<DataTemplate>

<TextBlockText="{Binding Path=Name} "/>

</DataTemplate>

</ListBox.ItemTemplate>

</ListBox&g t;

在後台,把ItemSource屬性設置為文件列表:

public WinCommandAndBinding() 
{
 InitializeComponent();
    
 FileInfo[] fileList = new DirectoryInfo("C:\\").GetFiles("*.*");
     
lbFile.ItemsSource = fileList;
 }

運行如下:

現在,再添加一個按鈕用來顯 示文件,但不希望任何文件都被打開。所以,要在加載的文件上提供某種類型的過濾器。現實現兩個命令Open 和Blocked並為他們提供某種類型的處理過程,代碼如下:

public static readonly RoutedCommand OpenCommand =
            new RoutedCommand("Open", typeof(WinCommandAndBinding));
    
        public static readonly RoutedCommand BlockedCommand =
            new RoutedCommand("Blocked", typeof(WinCommandAndBinding));
    
        public WinCommandAndBinding()
        {
            InitializeComponent();
    
            CommandBindings.Add(new CommandBinding (OpenCommand,
                delegate(object sender,ExecutedRoutedEventArgs e){
                    Process.Start("notepad.exe",(string)e.Parameter);}));
    
            CommandBindings.Add(new CommandBinding(BlockedCommand,
                delegate(object sender, ExecutedRoutedEventArgs e)
                {
                    MessageBox.Show((string)e.Parameter, "Blocked");
                }));
    
    
            FileInfo[] fileList = new DirectoryInfo("C:\\").GetFiles("*.*");
            lbFile.ItemsSource = fileList;
        }
    }

在定義好兩個命令後,就可以更新文件的數據模板來包含按鈕了。在命令參數(文件名)中使用數據 綁定。對應命令本身,由於希望某些條目用OpenCommand,而其他條目用BlockedCommand,所以將使用 IValueConvert把文件名轉換為ICommand,代碼如下:

<ListBox Margin="2" Name="lbFile">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <WrapPanel>
                        <TextBlock Text="{Binding Path=Name}"/>
                        <Button Margin="5" CommandParameter="{Binding Path=FullName}">
                            <Button.Command>
                                <Binding>
                                    <Binding.Converter>
                                        <local:FileToCommandConverter/>
                                    </Binding.Converter>
                                </Binding>
                            </Button.Command> Show
                        </Button>
                    </WrapPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

下面是轉換器:

public class FileToCommandConverter : 

IValueConverter
    {
        public object Convert(object value ,Type targetType,object parameter,CultureInfo 

culture)
        {
            string ext = ((FileInfo)value).Extension.ToLowerInvariant();
            if (ext == ".txt")
                return WinCommandAndBinding.OpenCommand;
            else
                return WinCommandAndBinding.BlockedCommand;
        }
        public object ConvertBack(object value, Type targetType, object parameter, 

System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

運行結果:

這個例子雖然有點微不足道, 不過可以使用CanExecute方法輕松地完成類似的行為,並針對“壞”文件禁用這個命令。然而,這裡最重要的 一點是,可以返回任何命令。可以使用任何基於數據的邏輯來確定任何元素的行為。

另外我們可以考 慮下能不能用數據觸發器實現呢?呵呵,可以的,這等於把命令、數據綁定和觸發器三者融合到一起了?是不 是很強大,呵呵下面是代碼:

<ListBox Margin="2" Name="lbFile2">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <WrapPanel>
                        <TextBlock Text="{Binding Path=Name}"/>
                        <Button x:Name="btnShow" Margin="5" CommandParameter="{Binding 

Path=FullName}"
                                Command="{x:Static local:WinCommandAndBinding.BlockedCommand}"
                                Content="  Block"/>
                    </WrapPanel>
                    <DataTemplate.Triggers>
                        <DataTrigger  Value=".txt">
                            <DataTrigger.Binding>
                                <Binding  Path='Extension'>
                                    <Binding.Converter>
                                        <local:ToLowerInvariantConvert/>
                                    </Binding.Converter>
                                </Binding>
                            </DataTrigger.Binding>
                            <Setter TargetName="btnShow"
                            Property="Command"
                                Value="{x:Static local:WinCommandAndBinding.OpenCommand}"/>
                            <Setter TargetName="btnShow" Property="Content" Value="Show"/>
                        </DataTrigger>
                    </DataTemplate.Triggers>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

轉換器:

public class ToLowerInvariantConvert : 

IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
      return  ((string)value).ToLowerInvariant();
           
    }
    public object ConvertBack(object value, Type targetType, object parameter, 

System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved