MVC和MVVM杂谈

简介: 代码不仅仅是一种技术,更是一种艺术,在艺术的领域中有了自己的设计模式,有了自己的框架……,任何东西都不是与生俱来的,而是随着人们的认识慢慢发现和总结,大脑的思维就在于此,可以发现规律和总结规律。 MVC和MVVM这两种模式对于NET下的开发者应该不会陌生,关于这两个我在以前的博客中介绍过,今天心血来潮,自己一个个的模拟下,纸上得来终觉浅,绝知此事要躬行,就我这破脑子,看过的东西,很快就被忘记,愚人自有愚人的办法。

代码不仅仅是一种技术,更是一种艺术,在艺术的领域中有了自己的设计模式,有了自己的框架……,任何东西都不是与生俱来的,而是随着人们的认识慢慢发现和总结,大脑的思维就在于此,可以发现规律和总结规律。

MVC和MVVM这两种模式对于NET下的开发者应该不会陌生,关于这两个我在以前的博客中介绍过,今天心血来潮,自己一个个的模拟下,纸上得来终觉浅,绝知此事要躬行,就我这破脑子,看过的东西,很快就被忘记,愚人自有愚人的办法。

 

刚开始的时候,我们写程序,对于NET的开发人员来说,都是在一个事件下面完成一个一个任务的,比如下面的操作:

 private void Button_Click(object sender, RoutedEventArgs e)
        {

string pName = Convert.ToDouble(textBox1.Text);
               
Double B
= Convert.ToDouble(textBox2.Text);

// 省略
//在这里对A和B进行操作,如果对Name,B换一种操作,那么必须进入视图这里操作


}

 

这样有一个好处就是代码很容易阅读,逻辑也很清楚,但是对于大的项目来说,这个缺点就很明显,业务和视图耦合的太紧密,我们知道写程序有一个目的就是解耦,所以上面这个必须改动,那么这个时候我们需要将业务处理逻辑和视图分开来写,在视图中声明一个事件或者委托变量,然后在需要的进行处理的类中进行绑定,如下:

  public event ClickEventHandler SendClick;
          
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            if (SendClick != null)
            {
                MyArgs pArgs = new MyArgs();
                pArgs.Name= textBox1.Text;
                pArgs.B = Convert.ToDouble(textBox2.Text);
                //A和B的操作在另外的类中,这样的好处,对于A,B可以有不同的操作,SendClick预先不知道自己如何对Name,B操作,如果要换一种操作,直接在绑定的类中进行修改,而不是在视图中修改,相比上面的,这里的优势不言而喻。
SendClick(
this, pArgs); } }

如果是视图是程序的外观或者外衣,那么数据就是这个程序的血液,没有血液的程序还能有什么用么?视图的目的就是为了显示数据,而如何显示数据,这个就好比人的神经中枢,控制着人的一切,通着类似,程序中应该有一个控制器,所以我们将程序中所使用的数据完完全全的放在一个类中,称之为数据模型,好比下面这个一样:

class Persons
    {
        List<Person> persList = new List<Person>();

        public Persons()
        {
            persList.Add(new Person("刘宇", 25));
            persList.Add(new Person("刘宇1", 25));
            persList.Add(new Person("刘宇2", 25));
        }
        public List<Person>  GetPersons()
        {
            return persList;
        }
    }

数据和视图都有了,控制器将这两者联系起来:

  public controller()
       {
           if (m_MVC == null)
           {
               m_MVC = new MVC(); //这是我们的视图
               m_MVC.SendClick += new ClickEventHandler(m_MVC_SendClick);
           }
           datamodel = new Persons().GetPersons();//这是我们的数据
       }

        void m_MVC_SendClick(object sender, MyArgs e)
        {

string sName=e.Name;

//这里对数据进行操作,这里我做了一个查找

          List<Person> pPersonsTest;
            if (!string.IsNullOrEmpty(sName))
            {
                pPersonsTest = new List<Person>();

 
 

                foreach (var p in pPersons)
                {
                    if (p.Name == sName)
                        pPersonsTest.Add(p);

                   //有了结果,可以在视图上显示,省略。

                   
                }

 
 

            }


        }

 

 

上面这个就算是一个MVC结构的小程序,数据和视图分开了,控制器用来对请求进行处理。

 

在MVVM中,这个可以进一步通过ICommand和绑定简化。

在视图中,我们也不需要对事件进行处理,也就是没有了Button_Click这样的方法,取之而来的是:


<Button Command="{Binding pCmd}" CommandParameter="{Binding ElementName=txtName, Path=Text}" Height="64" Grid.ColumnSpan="2" Grid.Row="1" Content="查找"></Button>

 public partial class View : UserControl
    {
       ViewModel  PVM= new ViewModel();
        public View()
        {
            InitializeComponent();
            this.DataContext = PVM;
        }

           }

 

这里出现了ViewModel,这个ViewModel实现了INotifyPropertyChanged接口,要不然怎么实现变更通知,这里有一个疑惑我没搞清楚,就是这个PropertyChanged事件是在什么时候赋值的,这个可能是系统实现的。

class ViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;//

        private string _str;

       // private View _View;

        public string Str
        {
            get { return _str; }
            set
            {
                _str = value;
                if (PropertyChanged != null)
                {
                    this.PropertyChanged(this, new PropertyChangedEventArgs(Str));
                }//封装在一个函数里面
            }
        }
        
        //View pView 在MVC中传入视图可以用来更新数据,但是在MVVM中通过绑定。
        public ViewModel()
        {
            
            pPersons = new Persons().GetPersons();

            pCmd = new MyCommand(search) { ISbool = true };

            

        }

        public ICommand pCmd { get; set; }
        public List<Person> pPersons;
        void search(string sName)
        {
            List<Person> pPersonsTest;
            if (!string.IsNullOrEmpty(sName))
            {
                pPersonsTest = new List<Person>();

                foreach (var p in pPersons)
                {
                    if (p.Name == sName)
                        pPersonsTest.Add(p);

                    
                }

            }
        }
    }

在ViewModel中有一个pCmd这个参数,这个是被绑定到按钮上的,当按钮接受到这个命令后,就会执行查询操作,代码如下:

 class MyCommand:ICommand
    {
       public delegate void handler(string sName) ;
       handler _handler;
        public bool ISbool{get;set;}

        public MyCommand(handler pHandler)
        {
            this._handler = pHandler;
            
        }

        public event EventHandler CanExecuteChanged;
        public bool CanExecute(object parameter)
        {
           
            return true;
            
         
        }


        public void Execute(object parameter)
        {
            if (!String.IsNullOrEmpty(parameter.ToString()))
            {
                if (CanExecuteChanged!=null)
                {
                    _handler(parameter.ToString());
                }
            }
        }
    }

对于这个CanExecuteChanged这个事件是什么时候有值的,我也不清楚,这个先放到这里暂且不管,在命令里其实也是通过回调函数来执行ViewModel中的方法,委托在这里着实起了很大的作用。在写程序的时候,主界面我们经常是布局,然后将试图作为用户控件,最后添加到主窗体中,在MVVM中,只需要在主窗体中声明试图,然后放到指定的位置即可:

 xmlns:local="clr-namespace:WpfMVVM"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <StackPanel>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition></RowDefinition>
                    <RowDefinition></RowDefinition>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition></ColumnDefinition>
                    <ColumnDefinition></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <local:View Grid.Column="1" Grid.Row="0"></local:View>

                           </Grid>
           
          
        </StackPanel>
        
    </Grid>

 

总算将这个写完了,但是对于这两个事件变量的值,我只是能跟踪到其有值,但是却不知道在哪里给赋值的?还望大家告知答案。

技术这个玩意,要深刻的体会,要深入的应用,这样才可能有出奇制胜的可能,在工作中也就有了事半功倍这个说法,其实上面讨论的很大程度上都是依靠委托,委托允许声明和实现的分离(其实接口也是可以的)。

 

 

相关文章
|
26天前
|
设计模式 存储 前端开发
MVVM、MVC、MVP三种常见软件架构设计模式的区别
MVC、MVP 和 MVVM 是三种常见的软件架构设计模式,主要通过分离关注点的方式来组织代码结构,优化开发效率。
44 12
|
2月前
|
设计模式 前端开发 JavaScript
浅谈MVC、MVP、MVVM框架模式
浅谈MVC、MVP、MVVM框架模式
42 0
|
2月前
|
前端开发
MVVM和MVC的原理以及它们的区别
MVVM和MVC的原理以及它们的区别
|
2月前
|
前端开发 数据安全/隐私保护
什么是mvvm,mvp、mvc和mvvm模式有什么区别?
什么是mvvm,mvp、mvc和mvvm模式有什么区别?
66 0
|
16天前
|
设计模式 存储 前端开发
【设计模式】MVC与MVVM详尽解读与实战指南
【设计模式】MVC与MVVM详尽解读与实战指南
29 0
|
20天前
|
前端开发 测试技术 API
探索安卓应用的架构演进:从MVC到MVVM
本篇文章将深入探讨安卓应用开发中的架构演进,特别关注从传统的MVC(Model-View-Controller)到现代流行的MVVM(Model-View-ViewModel)架构的转变。通过对比两种架构的设计理念、实现方式和实际应用案例,解析MVVM在提高代码可维护性和可测试性方面的优势。
23 0
|
2月前
|
前端开发 JavaScript 开发者
深入理解MVC和MVVM:构建现代Web应用的利器
深入理解MVC和MVVM:构建现代Web应用的利器
|
2月前
|
XML 前端开发 测试技术
安卓架构模式:MVC、MVP、MVVM及更多
【4月更文挑战第13天】本文探讨了安卓应用开发中的常见架构模式,包括MVC、MVP和MVVM,以及VIPER和Clean Architecture。MVC分离关注点,易于理解,但安卓不直接支持。MVP通过呈现器实现更清晰的分层和便于单元测试。MVVM利用数据绑定简化UI逻辑,适合声明式编程。开发者应根据项目需求、团队技能和维护周期选择合适架构,随着工具和框架的进步,未来将提供更多模块化、可测试性和敏捷性的解决方案。
|
2月前
|
前端开发 JavaScript
mvvm/mvc/mvp三者区别
mvvm/mvc/mvp三者区别
27 3
|
2月前
|
前端开发 JavaScript
Vue中mvvm/mvc/mvp三者区别
Vue中mvvm/mvc/mvp三者区别