WPF中的MVVM模式简单实现

前言:在之前实现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编程。在接下来的时间里,我打算写一些具有实战性的内容,因为我之前都是分享一些初级的入门系列,接下来打算分享一些实际的项目实现,以及领域驱动设计方面的内容,希望得到大家的督促和支持。

原文地址:https://www.cnblogs.com/ZaraNet/p/9898480.html

时间: 2024-07-31 02:46:37

WPF中的MVVM模式简单实现的相关文章

WPF中使用MVVM模式进行简单的数据绑定

计划慢慢整理自己在WPF学习和工作应用中的一些心得和想法,先从一个简单的用法说起 在WPF中,XAML标记语言中绑定数据,而数据源就是指定为ViewModel类,而非界面本身的逻辑代码类 这样一定程度上达到界面与业务逻辑分离的思想,UI层只需要对ViewModel类进行依赖,只要ViewModel公开出来的属性不变,界面层就不用根据业务逻辑变化而进行修改 这大概就是MVVM模式的一个基本出发点,配合WPF的依赖属性和命令等结合使用,会有更复杂的用法及更好的效果 这里先从一个简单的数据绑定用法为例

简单的介绍下WPF中的MVVM框架

最近在研究学习Swift,苹果希望它迅速取代复杂的Objective-C开发,引发了一大堆热潮去学它,放眼望去各个培训机构都已打着Swift开发0基础快速上手的招牌了.不过我觉得,等同于无C++基础上手学习C#一样,即使将来OC被淘汰,那也是N年之后的事情,如果真的要做IOS开发,趁现在Swift才刚开始,花那么几个月去了解一下OC绝对是一件有帮助的事情. 扯远了,我前几天刚接触到一个叫做mvvm的框架,发现很有意思,带着学习的态度来写点东西,不足之处一起研究.还有一个很重要的原因,我发现不少同

在 WPF 程序中使用 MVVM 模式

MVVM 模式是一个很久之前的技术了,最近因为一个项目的原因,需要使用 WPF 技术,所以,重新翻出来从前的一段程序,重温一下当年的技术. MVVM 模式 MVVM 实际上涉及三个部分,Model, View 和 ViewModel ,三者的关系如下图所示. 在三部分的关系中,视图显示的内容和操作完全依赖于 ViewModel. Model 是应用程序的核心,代表着最大.最重要的业务资产,因为它记录了所有复杂的业务实体.它们之间的关系以及它们的功能. Model 之上是 ViewModel.Vi

WPF ContextMenu 在MVVM模式中绑定 Command及使用CommandParameter传参

原文:WPF ContextMenu 在MVVM模式中绑定 Command及使用CommandParameter传参 ContextMenu无论定义在.cs或.xaml文件中,都不继承父级的DataContext,所以如果要绑定父级的DataContext,直接DataContext=“{Binding}”是行不通的 不能绑父级,但是能绑资源 第一步:定义一个中间类用来做资源对象 1 public class BindingProxy : Freezable 2 { 3 #region Over

angular中的MVVM模式

在开始介绍angular原理之前,我们有必要先了解下mvvm模式在angular中运用.虽然在angular社区一直将angular统称为前端MVC框架,同时angular团队也称它为MVW(Whatever)框架,但angular框架整体上更接近MVVM模式.下面是Igor Minar发布在Google+ https://plus.google.com/+IgorMinar/posts/DRUAkZmXjNV的文章内容: MVC vs MVVM vs MVP. What a controver

WPF中使用MVVM创建一个简单的框架

MVVM模式 一.MVVM模式概述 MVVM Pattern : Model\View\ViewModel View:视图.UI界面 ViewModel:ViewModel是对Model的封装,通过一系列属性暴露Model的状态,提供给View进行显示 Model:数据模型 使用MVVM模式可以将代码逻辑和UI进行分离,因此开发团队可以关注创建健壮的ViewModel类,而设计团队可以关注设计界面友好的View.要融合两个团队输出只需要在View的xaml上进行正确的绑定即可. 二.演示程序 下

WPF教程:MVVM模式的理解与应用

一.  什么是MVVM模式 MVVM是Model-View-ViewModel的简写.微软的WPF带来了新的技术体验,如Silverlight.音频.视频.3D.动画--.这导致了软件UI层更加细节化.可定制化.同时,在技术层面,WPF也带来了诸如Binding.Dependency Property.Routed Events.Command.DataTemplate.ControlTemplate等新特性.MVVM(Model-View-ViewModel)框架的由来便是MVP(Model-

WPF ContextMenu 在MVVM模式中无法绑定 Command的解决办法

ContextMenu无论定义在.cs或.xaml文件中,都不继承父级的DataContext,所以如果要绑定父级的DataContext,直接DataContext=“{Binding}”是行不通的 不能绑父级,但是能绑资源 第一步:定义一个中间类用来做资源对象 1 public class BindingProxy : Freezable 2 { 3 #region Overrides of Freezable 4 5 protected override Freezable CreateI

WPF中StringToImage和BoolToImage简单用法

在WPF的绑定控件操作中,经常会通过bool值或者某些特定的string值做出相应动作.但UI层控件的很多属性对应的都不是Bool值或者对应的只是固定的String值. 这个时候有两方法解决该问题. 1.是在后台cs中做出比较判断,然后根据相应结果传达UI层做出相应动作. 2.是直接在UI界面写好,然后会自行根据传入值做相应动作. 本文主要讲第二种方法.Demo在结尾会附上. 一.基类,判断类代码(Bool篇) public class BoolToValueConverter<T> : IV