65.9K
CodeProject 正在变化。 阅读更多。
Home

MVVM Silverlight 4.0 简体中文

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.35/5 (9投票s)

2010年11月11日

CPOL

4分钟阅读

viewsIcon

56495

downloadIcon

1972

在 Silverlight 4.0 中实现 MVVM 模式

引言

MVVM 是一种基于 MVC/MVP 模式的设计模式,它们都试图解决类似的问题。MVVM 模式旨在分离紧密耦合的 UI 代码,包括渲染、控件操作和数据绑定代码。

为了学习方便,我将代码写得非常简单。我将代码以渐进但完整的方式打包,以便您可以根据需要选择学习的程度。

背景

对于像我这样花了八年时间熟悉“页面后代码”模型的人来说,MVVM 模式最初可能会让人望而生畏。但我很快发现事实并非如此,通过适应这种代码范式的转变,我们可以真正受益匪浅。我想特别感谢 Prabhjot Bakshi 的精彩文章,Brian Pring 用他精彩的演示向我介绍了 Silverlight,以及 Stephen Olah,他积极地促进了我的学习体验。 我希望我学习该模式的经验能对他人有所帮助。

MVVM 概念

MVVM 模式包含 3 个部分

  1. 视图
  2. ViewModel
  3. 模型

视图绑定到 ViewModel,模型中的任何更改都会自动反映在视图中。ViewModel 将处理模型中的任何更改,并接收视图上触发的事件。是的,就是这么简单!

MVVM.jpg

第一部分

在这里,我想介绍 MVVM 模式的基本概念,它有助于将 UI 代码逻辑上分离为 View(视图)、ViewModel(视图模型)和 Model(模型)。

视图

View 包含渲染 Silverlight 应用程序 UI 的代码,其中将包含您的 XAML 代码。理想情况下,要真正实现 MVVM 模式,我们希望避免任何代码隐藏。这意味着我们需要在 XAML 中将 View 连接到 ViewModel。您需要特别注意此部分细节,因为这可以为您节省大量调试时间。

首先,我在 `UserControl` 属性列表中注册 `ViewModel` 命名空间。

xmlns  :  local  ="clr-namespace:MVVMApp.ViewModel"     

在我的视图中,我有一个外部的 `Grid`,我将其连接到我的 `ViewModel`

<grid.datacontext>
            <local:contactviewmodel>
        </local:contactviewmodel></grid.datacontext> 

然后有一个内部的 `Grid`,我将其绑定到模型的一个实例

 <Grid DataContext="{Binding Path=mycontact}">

最后,将属性绑定到实际渲染我的文本/数据的控件。

<textbox grid.row="0" text="{Binding Path=FirstName }">
            <textbox grid.row="1" text="{Binding Path=SecondName }">
</textbox></textbox>

ViewModel

这是棘手的部分,将 `ViewModel` 视为一个连接到模型的专用代理。在 ASP.NET 中,您可以将其视为代码隐藏,您将在其中处理事件代码和数据绑定。

public class ContactViewModel
    {
        public Contact mycontact { get; set; }

        public   ContactViewModel()
        {
            Contact cont = new Contact();
            cont.FirstName = "Ritesh";
            cont.SecondName = "Ramesh";
            mycontact = cont;
        }
    }

模型

将 Model 视为包含数据的结构。Model 不会实现任何功能。但是,要在 MVVM 模式中使用 Model,我们需要 Model 实现 `INotifyPropertyChanged` 接口。`INotifyPropertyChanged` 接口用于通知客户端(通常是绑定客户端),属性值已更改。

我的模型有两个属性 `FirstName` 和 `SecondName`,并实现了 `INotifyPropertyChanged` 接口。`NotifyPropertyChanged` 方法检查属性是否有效,并向我的视图通知属性更改。

public class Contact :  INotifyPropertyChanged
    {
        private string _FirstName;
        public string FirstName { 
            get { return _FirstName; } 
            set { _FirstName = value;
            NotifyPropertyChanged("FirstName");
            } 
        }

        private string _SecondName;
        public string SecondName { 
            get { return _SecondName; } 
            set { _SecondName = value;
            NotifyPropertyChanged("SecondName");
            } 
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
    }

第二部分

在这里,我想进入 MVVM 模式的下一个阶段。即使用按钮控件实现命令,该命令将触发 ViewModel 中 View 和 Model 之间的自动数据绑定。

视图

我在 View 的现有 XAML 中添加了以下按钮语法。

 <Button Grid.Row="2"  Command="{Binding Path=DataContext.GetContact , 
	ElementName= LayoutRoot }" Content="View"
                    CommandParameter="{Binding Path=Phone}" />

ViewModel

这是实现按钮执行的大部分更改的地方。

在我的 ViewModel 中,我引入了一个 `GenericCommand` 类,它实现了 `ICommand` 接口,公开了 `CanExecute`、`Execute` 方法和一个 `CanExecuteChanged` 事件。

  • `CanExecute` - 在这里,您可以实现任何需要在调用执行之前检查的验证代码。在我的代码中,我将其设置为始终返回 `true`。
  • `Execute` - 在这里,您可以实现按钮单击事件上需要执行的任何代码。
  • `CanExecuteChanged` - 当影响命令是否应执行的更改发生时触发。
public    class  GenricCommand  :  ICommand  
 { 
ContactViewModel _vm; 
public GenricCommand( ContactViewModel  vm) 
           {  
               _vm = vm; 
           } 

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

         public   event   EventHandler 
CanExecuteChanged; 

            public   void  Execute( object 
parameter) 
          { 
              _vm.showContact( ); 
           } 
      } 

此外,我还修改了我的 `ViewModel` 类,添加了一个名为 `GetContact` 的方法,该方法返回我的 `GenricCommand` 类的一个对象。

   public ICommand GetContact
         {
             get { return new GenricCommand(this); }
        }

这反过来会将按钮单击执行的代码委托给我的 ViewModel 中包含的 `showContact` 方法。

   public  void showContact()
         {          
             mycontact.FirstName = "Ritesh";
             mycontact.SecondName = "Ramesh";   
        } 

模型

我的模型不需要任何更改。

关注点

  • 这只是 MVVM 模式的一种实现方式,还有许多其他方法可以实现相同的功能。
  • ViewModel 到底应该包含什么仍然非常有争议,例如,我应该在 View 本身中实现 `datagrid` 的排序,还是需要在 ViewModel 中实现该功能对我来说仍然是个谜?

参考文献

© . All rights reserved.