基本MVVM 和 ICommand用法舉例(轉)


 

引言

在本貼中,我們將學習WPF Commands。 Commands 可以很好地與 MVVM 模式 (Model- View-ViewModel)結合在一起。我們也將看到,視圖(view)實際上是怎樣知道和怎樣調用它的使用WPF 命令( Commands )的視圖模型(ViewModel)。

背景

下面我們一步一步討論而不是立即查看完整的代碼,這也可以較好地幫助我們理解代碼的每一部分。

讓我們看一下MVVM的體系結構。

 

 

我們約定使用下列標准術語:

  • Views 表示后綴為view的文件名 。(例如: StudentListView)
  • ViewModels 表示后綴為ViewModel的文件。(例如:StudentListViewModel)
  • Models 表示后綴為Model的文件。 (例如: StudentModel).

使用代碼

原理介紹已經足夠了。下面深入代碼了解一個可以工作的MVVM例子,了解怎樣在MVVM使用命令。

使用 Visual Studio 建立一個新WPF項目。按照上面的約定,把文件名MainWindow更改為 MainWindowView。

接着,我們需要建立一個新的類,名字為 MainWindowViewModel ,它將擔當視圖MainWindowView的視圖模型ViewModel)。

我們在這里所做的是,在MVVM內,我們告訴視圖,它的視圖模型是什么。這可以通過為視圖設置 Data Context來完成。在視圖模型文件里有ViewModel,然而他們現在還不具有某些特定的視圖之間的任何連接。

設置Datacontext的代碼看起來是下面的樣子。

打開 MainWindowView.xaml.cs並設置 data context 如下。

MainWindowView.xaml.cs

 
<Window x:Class="WpfExample.MainWindowView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        xmlns:local="clr-namespace:WpfExample">

    <Window.DataContext>
        <local:MainWindowViewModel/>
    </Window.DataContext>

    <Grid>
    </Grid>
</Window>

這里的本地命名空間別名為WpfExample。這是必要的,這樣 framework知道MainWindowViewModel在哪里可以找到。

我們通過一個簡單的綁定來驗證這個。

讓我們添加一個button查看,使用視圖模型的一個實例設置button的content 。

視圖

添加一個查看按鈕並設置它的綁定內容如下。

MainWindowView.xaml.cs 

<Window x:Class=" WpfMvvmExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:local="clr-namespace:WpfMvvmExample"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">

    <Window.DataContext>
        <local:MainWindowViewModel/>
    </Window.DataContext>

    <Grid>
        <Button Width="100" 
        Height="100" Content="{Binding ButtonContent}"/>
    </Grid>
</Window>

視圖模型

1
2
3
4
5
6
7
8
9
10
11
12
13
namespace  WpfExample
{
     class  MainWindowViewModel
     {
         public  string  ButtonContent
         {
             get
             {
                 return  "Click Me" ;
             }
         }
     }
}

在上面代碼中,我們告訴視圖,從視圖模型所呈現的ButtonContent屬性獲取按鈕的內容。

<Button Width="100" Height="100" Content="{Binding ButtonContent}"/>

現在如果運行應用,我們可以看到按鈕的內容為 字符串(string) Click Me”.

這表明我們的MVVM可以正常工作。

現在我們轉移到ICommand 接口(ICommand Interface)

現在,我們使用WPF命令為按鈕添加一個點擊功能。

在MVVM中,命令為通過視圖更新模型提供了一種機制。

首先,我們看一下ICommand接口。

bool CanExecute(object parameter);
void Execute(object parameter);
event EventHandler CanExecuteChanged;

我們建立一個應用樣板。當點擊按鈕時顯示一個“HI"消息框,我們添加另一個按鈕,切換hi按鈕是否可以點擊。

我們建立一個RelayCommand類,實現ICommand接口。這個類增強ICommand並分離代碼作為一個獨立的類。

This class acts as Enhancement for the ICommand and extracts the boiler plate code to a separate class.

public class RelayCommand : ICommand
   {
       private Action<object> execute;                     //定義成員

       private Predicate<object> canExecute;//Predicate:述語//定義成員

       private event EventHandler CanExecuteChangedInternal;//事件

       public RelayCommand(Action<object> execute)       //定義Action,CanExecute
           : this(execute, DefaultCanExecute)
       {
       }

       public RelayCommand(Action<object> execute, Predicate<object> canExecute)//定義
       {
           if (execute == null)
           {
               throw new ArgumentNullException("execute");
           }

           if (canExecute == null)
           {
               throw new ArgumentNullException("canExecute");
           }

           this.execute = execute;
           this.canExecute = canExecute;
       }

       public event EventHandler CanExecuteChanged        //CanExecuteChanged事件處理方法
       {
           add
           {
               CommandManager.RequerySuggested += value;
               this.CanExecuteChangedInternal += value;
           }

           remove
           {
               CommandManager.RequerySuggested -= value;
               this.CanExecuteChangedInternal -= value;
           }
       }

       public bool CanExecute(object parameter)            //CanExecute方法
       {
           return this.canExecute != null && this.canExecute(parameter);
       }

       public void Execute(object parameter)              //Execute方法
       {
           this.execute(parameter);
       }

       public void OnCanExecuteChanged()                //OnCanExecute方法
       {
           EventHandler handler = this.CanExecuteChangedInternal;
           if (handler != null)
           {
               //DispatcherHelper.BeginInvokeOnUIThread(() => handler.Invoke(this, EventArgs.Empty));
               handler.Invoke(this, EventArgs.Empty);
           }
       }

       public void Destroy()                          //銷毀方法
       {
           this.canExecute = _ => false;
           this.execute = _ => { return; };
       }

       private static bool DefaultCanExecute(object parameter)  //DefaultCanExecute方法
       {
           return true;
       }
   }

CommandManager.RequerySuggested 負責使能和禁用 "Click to Hii" 按鈕.

視圖

<Window x:Class="WpfExample.MainWindowView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        xmlns:local="clr-namespace:WpfExample">

    <Window.DataContext>
        <local:MainWindowViewModel/>
    </Window.DataContext>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition/>
        </Grid.RowDefinitions>

        <Button Grid.Row="0" Command="{Binding HiButtonCommand}" 
        CommandParameter="Hai" Content="{Binding HiButtonContent}"
                Width="100"
                Height="100"  />

        <Button Grid.Row="1" Content="Toggle Can Click" 
        Command="{Binding ToggleExecuteCommand}"  Width="100" Height="100"/>
    </Grid>

</Window>

視圖模型

class MainWindowViewModel
    {
        private ICommand hiButtonCommand;

        private ICommand toggleExecuteCommand { get; set; }

        private bool canExecute = true;    //初始化為true

        public string HiButtonContent      //定義公開屬性
        {
            get
            {
                return "click to hi";
            }
        }

        public bool CanExecute               //定義公開屬性
        {
            get
            {
                return this.canExecute;
            }

            set
            {
                if (this.canExecute == value)
                {
                    return;
                }

                this.canExecute = value;
            }
        }

        public ICommand ToggleExecuteCommand      //定義接口
        {
            get
            {
                return toggleExecuteCommand;
            }
            set
            {
                toggleExecuteCommand = value;
            }
        }

        public ICommand HiButtonCommand          //定義接口
        {
            get
            {
                return hiButtonCommand;
            }
            set
            {
                hiButtonCommand = value;
            }
        }

        public MainWindowViewModel()               //構造函數
        {
            HiButtonCommand = new RelayCommand(ShowMessage, param => this.canExecute);
            toggleExecuteCommand = new RelayCommand(ChangeCanExecute);
        }

        public void ShowMessage(object obj)       //消息 方法
        {
            MessageBox.Show(obj.ToString());
        }

        public void ChangeCanExecute(object obj)  //方法
        {
            canExecute = !canExecute;
        }
    }

最后的運行結果好像是這樣:


免責聲明!

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



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