【发布时间】:2010-10-25 13:04:17
【问题描述】:
通过this question的慷慨帮助,我整理了以下MVVM结构,它在XAML(当前日期/时间)中实时显示模型的变化,非常好。
这种设置的一个很酷的优势是 当你看你的观点时 Visual Studio 的设计模式 或 混合,你看到时间在流逝, 这意味着在设计时你 可以访问您的实时数据 模型。
在实现此功能的过程中,我惊讶地发现大部分内容从我的 ViewModel 转移到了我的模型中,包括 INotifyPropertyChange 的实现。另一个变化是我不再绑定到 ViewModel 上的 properties,而是绑定到 methods。
所以目前这是我最喜欢的 MVVM 风格:
-
视图很笨:
- 一个 ObjectDataProvider 用于您模型中需要的每个对象
- 每个 ObjectDataProvider 都映射到 ViewModel 上的一个方法(不是属性)
- XAML 元素中没有 x:Name 属性
-
ViewModel 很瘦:
- ViewModel 中唯一的东西是视图绑定的方法
-
模特很胖:
- 模型在其每个属性上实现 INotifyPropertyChanged。
- 对于您的 ViewModel 上的每个方法(例如 GetCurrentCustomer),您的模型(例如 GetCurrentCustomer)中都有一个对应的单例方法。
- 该模型负责处理本示例中的任何实时线程功能
问题:
- 在实际场景中实现 MVVM 的各位,这是否也是你们确定的基本结构,如果不是,你们的有何不同?
- 如何扩展它以包括路由命令和路由事件?
如果您只是将 XAML 和后面的代码复制到新的 WPF 项目中,则以下代码将起作用。
XAML:
<Window x:Class="TestBinding99382.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestBinding99382"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<ObjectDataProvider
x:Key="DataSourceCustomer"
ObjectType="{x:Type local:ShowCustomerViewModel}"
MethodName="GetCurrentCustomer"/>
</Window.Resources>
<DockPanel DataContext="{StaticResource DataSourceCustomer}">
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<TextBlock Text="{Binding Path=FirstName}"/>
<TextBlock Text=" "/>
<TextBlock Text="{Binding Path=LastName}"/>
</StackPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<TextBlock Text="{Binding Path=TimeOfMostRecentActivity}"/>
</StackPanel>
</DockPanel>
</Window>
代码背后:
using System.Windows;
using System.ComponentModel;
using System;
using System.Threading;
namespace TestBinding99382
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
}
//view model
public class ShowCustomerViewModel
{
public Customer GetCurrentCustomer() {
return Customer.GetCurrentCustomer();
}
}
//model
public class Customer : INotifyPropertyChanged
{
private string _firstName;
private string _lastName;
private DateTime _timeOfMostRecentActivity;
private static Customer _currentCustomer;
private Timer _timer;
public string FirstName
{
get
{
return _firstName;
}
set
{
_firstName = value;
this.RaisePropertyChanged("FirstName");
}
}
public string LastName
{
get
{
return _lastName;
}
set
{
_lastName = value;
this.RaisePropertyChanged("LastName");
}
}
public DateTime TimeOfMostRecentActivity
{
get
{
return _timeOfMostRecentActivity;
}
set
{
_timeOfMostRecentActivity = value;
this.RaisePropertyChanged("TimeOfMostRecentActivity");
}
}
public Customer()
{
_timer = new Timer(UpdateDateTime, null, 0, 1000);
}
private void UpdateDateTime(object state)
{
TimeOfMostRecentActivity = DateTime.Now;
}
public static Customer GetCurrentCustomer()
{
if (_currentCustomer == null)
{
_currentCustomer = new Customer
{ FirstName = "Jim"
, LastName = "Smith"
, TimeOfMostRecentActivity = DateTime.Now
};
}
return _currentCustomer;
}
//INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
}
【问题讨论】:
-
关于 RelayCommands 和 RoutedCommands,您可能想看看这些答案:stackoverflow.com/questions/650010/…
标签: wpf mvvm architecture