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>

 

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

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

 

 

相关文章
|
3月前
|
设计模式 前端开发 JavaScript
浅谈MVC、MVP、MVVM框架模式
浅谈MVC、MVP、MVVM框架模式
30 0
|
4月前
|
前端开发
MVVM和MVC的原理以及它们的区别
MVVM和MVC的原理以及它们的区别
|
1月前
|
前端开发 数据安全/隐私保护
什么是mvvm,mvp、mvc和mvvm模式有什么区别?
什么是mvvm,mvp、mvc和mvvm模式有什么区别?
33 0
|
2月前
|
存储 前端开发 JavaScript
什么是MVVM?MVC、MVP与MVVM模式的区别?
什么是MVVM?MVC、MVP与MVVM模式的区别?
|
3月前
|
存储 开发框架 前端开发
MVVM 模式与 MVC 模式:构建高效应用的选择
MVVM 模式与 MVC 模式:构建高效应用的选择
MVVM 模式与 MVC 模式:构建高效应用的选择
|
3月前
|
前端开发 JavaScript 数据可视化
|
3月前
|
设计模式 存储 前端开发
【各种问题处理】MVC、MVP、MVVM 、MVI、VIPER 架构(设计模式)
【1月更文挑战第13天】【各种问题处理】MVC、MVP、MVVM 、MVI、VIPER 架构(设计模式)
|
3月前
|
设计模式 前端开发 数据可视化
前端框架中 MVC 和 MVVM 两种设计方式的区别
前端框架中 MVC 和 MVVM 两种设计方式的区别
16 0
|
4月前
|
前端开发 测试技术 数据处理
MVVM和MVC以及MVP的原理以及它们的区别
MVVM和MVC以及MVP的原理以及它们的区别
40 0
|
8月前
|
前端开发 JavaScript UED