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

MVVM - 演示

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.43/5 (31投票s)

2012年8月6日

CPOL

4分钟阅读

viewsIcon

152433

downloadIcon

12146

如果你是 MVVM 的新手,这里是开始的地方。通过一个例子解释 MVVM。

MVVM

模型-视图-视图模型通常是 WPF 模式。它由一个视图组成,该视图获取所有用户输入并将其转发到视图模型,通常使用命令。视图通过使用数据绑定主动从视图模型中提取数据。模型不知道视图模型,而视图模型也不知道视图。

通过一个例子解释 MVVM

让我们使用 MVVM 创建一个示例患者管理应用程序。逐步进行,我们必须首先定义我们的模型,然后定义视图模型,最后定义视图。

步骤 1 - 创建模型

定义:模型通常被称为领域模型,完全独立于 UI,它存储状态并有助于处理问题领域。

在我们的示例中,模型成为 DOM 对象,它只是患者实体。下面的示例显示了患者实体。

public class Patient
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Int64 MobileNumber { get; set; }
}   

步骤 2 – 创建视图模型

定义:该术语的意思是“视图的模型”,可以被认为是视图的抽象,但它也提供了视图可以用于数据绑定的模型的专门化。在后一种角色中,视图模型包含将模型类型转换为视图类型的数据转换器,并且包含视图可用于与模型交互的命令。视图模型类似于数据的概念状态,而不是模型中数据的真实状态。 

回到我们的例子,让我们创建 PatientViewModel,它将公开属性(包含数据)和命令(用户操作),这些属性和命令将被绑定到视图。

公共属性 

需要绑定到视图的所有数据都将作为公共属性公开。视图模型将实现 PropertyChanged 事件,以便在视图模型发生更改时自动更新视图。为此,我们在设置属性时触发 PropertyChanged 事件。

public class PatientDetailViewModel: INotifyPropertyChanged
{
//    ...
    public int Id
    {
        get { return domObject.Id; }
        set
        {
       domObject.Id = value;
       OnPropertyChanged("Id");
        }
    }
//    ...
    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
           PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
} 

命令
定义:主要思想是将整个演示逻辑移动到视图模型。这可以通过使用 WPF 的另一个功能来实现,即命令。命令可以像数据一样绑定,并被许多元素(如按钮、切换按钮、菜单项、复选框和输入绑定)支持。这里的目标是在视图的代码隐藏中没有任何逻辑行。

视图将在用户操作时执行命令,命令将在视图模型中实现。为此,您不能使用标准的 WPF RoutedUIEvent,但您可以轻松开发自己的命令类。一种常见的方法是创建一个命令对象,该对象调用您指定的委托。
这是一个示例,说明如何定义自定义命令类,您稍后将在视图模型中定义命令时使用它。

public class RelayCommand : ICommand
{
    readonly Action<object> _execute;
    readonly Predicate<object> _canExecute;

    public RelayCommand(Action<object> execute)
        : this(execute, null){}

    public RelayCommand(Action<object> execute,
Predicate<object> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");
        _execute = execute;
        _canExecute = canExecute;
    }

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

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

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

回到我们的例子,我们的示例应用程序需要添加、删除和搜索功能。该示例演示了如何使用我们上面定义的 RelayCommand 实现 Add 命令。

public class PatientDetailViewModel: INotifyPropertyChanged
{
    public ICommand AddPatientCmd { get { return _addPatientCmd; } }
    public PatientDetailViewModel()
    {
        _addPatientCmd = new RelayCommand(Add, CanAdd);
    }

    public bool CanAdd(object obj)     {  //Logic   }
    public void Add(object obj)  {  //Logic   }
} 

步骤 3 – 创建视图

定义:视图在 XAML 中定义,不应在代码隐藏中包含任何逻辑。它仅通过使用数据绑定绑定到视图模型。视图主要涉及设置 UI 和绑定到视图模型。此控件的 DataContext 属性将设置为视图模型。

由于我们已经创建了 PatientViewModel,我们需要做的就是创建 PatientDetailView,然后将 ViewModel 绑定为 DataContext。此示例显示了属性绑定和命令绑定。

<UserControl ...>
    <!--Bind the View Model to the View. -->
    <UserControl.DataContext>
       <ViewModels:PatientDetailViewModel/>
    </UserControl.DataContext>
    ....
    <TextBox Name="TbxName" .... 
         Text="{Binding Path=Name}"/>    
    ....
    <Button Name="BtnAdd" Content="Add" ....
        Command="{Binding AddPatientCmd}"/>   
.....             
</UserControl>

注意事项 

由于在实际项目中,您通常每个视图有多个数据对象,因此使用视图模型变得很方便,因为您可以将所有数据对象聚合到一个公开聚合数据作为属性并且可以绑定到 DataContext 的单个视图模型中。

MVVM 的关键点是使视图完全关注数据的外观,而不是行为。理想情况下,视图应该是完全即插即用的,唯一的工作是将绑定连接到 ViewModel。

此外,将所有行为与 GUI 分离使您可以在单元测试中更加完整。

© . All rights reserved.