1. 程式人生 > >WPF中的MVVM模式簡單實現

WPF中的MVVM模式簡單實現

hand bar alt 入門 right 一個 suggest too center

前言:在之前實現WPF程序時,我們可能會把所有的後臺邏輯都放在視圖的後臺文件中,這樣的實現方式的好處更直觀,方便,對於一些小的應用程序這樣做當然沒什麽問題,但是對於復雜的應用程序這樣寫的話,可能會導致後臺代碼顯得非常臃腫,到最好變得難以維護。此時想到的解決方案就是職責分離,使後臺的邏輯分離到其他類中,MVVM其實我理解就是達到這個目的。下面我們按照MVVM的組成部分來實現下這個MVVM程序。

public class Person
    {
        public string Name { get; set; }
        public int Age { get; set
; } }

為了進行測試,下面創建一個靜態方法來獲得測試數據。

技術分享圖片
public class PersonDataHelper
    {
        public static ObservableCollection<Person> GetPersons()
        {
            ObservableCollection<Person> samplePersons = new ObservableCollection<Person>();
            samplePersons.Add(new Person() {Name = "張三", Age = 33});
            samplePersons.Add(new Person() { Name ="王五", Age= 22 });
            samplePersons.Add(new Person() { Name = "李四", Age = 35 });
            samplePersons.Add(new Person() { Name = "LearningHard", Age = 27 });
            return samplePersons;
        }
    }
技術分享圖片

  第二步:實現ViewModel層,實現數據和界面之間的邏輯。在視圖模型類中,包含了屬性和命令,因為在MVVM中,事件都當成命令來進行處理,其中命令只能與具有Command屬性的控件進行綁定。既然要包含命令,首先就需要實現一個命令,這裏自定義的命令需要實現ICommand接口。這裏我們定義了一個QueryCommand。具體的實現代碼如下所示:

public class QueryCommand :ICommand
    {
        #region Fields
        private Action _execute;
        private Func<bool> _canExecute;
        #endregion 

        public QueryCommand(Action execute)
            : this(execute, null)
        { 
        }
        public QueryCommand(Action execute, Func<bool> canExecute)
        {
            if (execute == null)
                throw new ArgumentNullException("execute");
            _execute = execute;
            _canExecute = canExecute;
        }

        #region ICommand Member

        public event EventHandler CanExecuteChanged
        {
            add
            {
                if (_canExecute != null)
                {
                    CommandManager.RequerySuggested += value;

                }
            }
            remove
            {
                if (_canExecute != null)
                {
                    CommandManager.RequerySuggested -= value;

                }
            }
        }

        public bool CanExecute(object parameter)
        {
            return _canExecute == null ? true : _canExecute();
        }

        public void Execute(object parameter)
        {
            _execute();
        }
        #endregion
    }

  

  接下來就是定義我們的ViewModel類了,具體的實現代碼如下所示:

public class PersonListViewModel : INotifyPropertyChanged
    {
        #region Fields
        private string _searchText;
        private ObservableCollection<Person> _resultList;
        #endregion 

        #region Properties

        public ObservableCollection<Person> PersonList { get; private set; }

        // 查詢關鍵字
        public string SearchText
        {
            get { return _searchText; }
            set
            {
                _searchText = value;
                RaisePropertyChanged("SearchText");
            }
        }

        // 查詢結果
        public ObservableCollection<Person> ResultList
        {
            get { return _resultList; }
            set
            {
                _resultList = value;
                RaisePropertyChanged("ResultList");
            }
        }

        public ICommand QueryCommand 
        { 
            get { return new QueryCommand(Searching, CanSearching); } 
        }

        #endregion 

        #region Construction
        public PersonListViewModel()
        {
            PersonList = PersonDataHelper.GetPersons();
            _resultList = PersonList;
        }

        #endregion
        
        #region Command Handler
        public void Searching()
        {
            ObservableCollection<Person> personList = null;
            if (string.IsNullOrWhiteSpace(SearchText))
            {
                ResultList = PersonList;
            }
            else
            {
                personList = new ObservableCollection<Person>();
                foreach (Person p in PersonList)
                {
                    if (p.Name.Contains(SearchText))
                    {
                        personList.Add(p);
                    }
                }
                if (personList != null)
                {
                    ResultList = personList;
                }
            }
        }

        public bool CanSearching()
        {
            return true;
        }

        #endregion 

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region Methods
        private void RaisePropertyChanged(string propertyName)
        {
            // take a copy to prevent thread issues
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion 
    }

  第三步:實現View層,設計我們的視圖,設置它的DataContext屬性為ViewModel類。具體的XAML代碼如下所示:

<Window x:Class="MVVMDemo.View.PersonsView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:MVVMDemo.ViewModel"
        Title="PersonsView" Height="350" Width="400">
    <!--設置DataContex是ViewModel類,當然你也可以使用後臺代碼設置-->
    <Window.DataContext>
        <local:PersonListViewModel />
    </Window.DataContext>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <TextBox Grid.Row="0" Name="searchtxt" Text="{Binding  Path=SearchText, Mode=TwoWay}" HorizontalAlignment="Left" Height="30" Width="280" Margin="10,0,0,0"></TextBox>
        <Button Grid.Row="0" Name="searchBtn" Content="Search" Command="{Binding Path=QueryCommand}" Width="80" Height="30" HorizontalAlignment="Right" Margin="0,0,10,0"></Button>
        <DataGrid Grid.Row="1" Name="datGrid" 
                  HorizontalAlignment="Center"
                  VerticalAlignment="Top" ItemsSource="{Binding Path=ResultList}" Width="300"></DataGrid>
        
    </Grid>
</Window>

  到此,我們的MVVM的WPF程序就已經完成了,下面就是要看看程序是否達到我們預期的目的。具體的運行結果如下圖所示:

技術分享圖片

四、總結

  到這裏,本文的內容就分享完了,並且本文也是WPF系列的最後一篇了,希望這個系列可以使得初學者快速上手WPF編程。在接下來的時間裏,我打算寫一些具有實戰性的內容,因為我之前都是分享一些初級的入門系列,接下來打算分享一些實際的項目實現,以及領域驅動設計方面的內容,希望得到大家的督促和支持。

WPF中的MVVM模式簡單實現