通过 this question 上的慷慨帮助,我把下面的 MVVM 结构放在一起,它在 XAML(当前日期/时间)中实时显示模型的变化,非常好。
A cool advantage of this set up is that when you look at your view in design mode of Visual Studio or Blend, you see the time ticking by, which means that at design time you have access to live data from your model.
在让它工作的过程中,我很惊讶地看到 大部分内容从我的 ViewModel 转移到我的模型 ,包括 INotifyPropertyChange 的实现。另一个变化是我不再绑定(bind)到 ViewModel 上的属性,而是绑定(bind)到方法 .
所以目前这是我最喜欢的 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));
}
}
}
}
最佳答案
这是我的意见,因为它的值(value):
我不太同意您建议的方法(愚蠢的观点除外)。在现实生活中,您通常必须使用现有模型:它可能是您没有时间(或将)更改的遗留代码,甚至是您没有代码的库。在我看来,模型应该完全不知道它的显示方式,并且应该可以在非 WPF 应用程序中轻松使用。所以它不必实现任何特定的接口(interface),如 INotifyPropertyChanged
的 INotifyCollectionChanged
使其在 MVVM 中可用。我认为所有与 UI 相关的逻辑都应该驻留在 ViewModel 中。
关于RoutedEvents
和 RoutedCommands
,它们并不真正适合与 MVVM 模式一起使用。我通常尽量少用RoutedEvents
尽可能,没有RoutedCommands
一点也不。相反,我的 ViewModel 公开了 RelayCommand
我在 XAML 中绑定(bind)到 UI 的属性(有关 RelayCommand
的详细信息,请参阅 Josh Smith 的 this article)。当我真的需要为某些控件处理事件时,我使用附加的行为将事件映射到 ViewModel 命令(查看 Marlon Grech's implementation)
所以,总而言之:
当然这只是我的方法,它可能不是最好的,但我觉得很舒服;)
关于wpf - 胖模型、瘦 View 模型和哑 View ,最好的 MVVM 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/852441/