我有一个小型测试 WPF MVVM 应用程序在其中工作,其中一个视图允许用户更改客户的名字或姓氏,并且全名会自动更改,因此通信从 M 到 MV 到 V 并返回,一切都完全解耦,到目前为止一切顺利。
但是现在,当我考虑如何开始扩展它以使用 MVVM 模式构建大型应用程序时,我发现解耦是一个障碍,即:
我将如何进行验证消息,例如,如果回到 LastName 设置器中的模型中,我添加了阻止设置超过 50 个字符的名称的代码,我如何向视图发送消息,告诉它显示名称太长的?
在复杂的应用程序中,我可能一次在屏幕上有几十个视图,但我知道在 MVVM 中,每个视图都有一个且只有一个 ViewModel 分配给它来为其提供数据和行为,那么视图如何交互例如,在上面的验证示例中,如果回到客户模型中,我们想要通知特定的“MessageAreaView”以显示消息“姓氏可能只包含 50 个字符。”,我们如何在堆栈中进行通信到那个特定的观点?
CustomerHeaderView.xaml(视图):
<UserControl x:Class="TestMvvm444.Views.CustomerHeaderView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<StackPanel HorizontalAlignment="Left">
<ItemsControl ItemsSource="{Binding Path=Customers}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<StackPanel Orientation="Horizontal">
<TextBox
Text="{Binding Path=FirstName, Mode=TwoWay}"
Width="100"
Margin="3 5 3 5"/>
<TextBox
Text="{Binding Path=LastName, Mode=TwoWay}"
Width="100"
Margin="0 5 3 5"/>
<TextBlock
Text="{Binding Path=FullName, Mode=OneWay}"
Margin="0 5 3 5"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Grid>
</UserControl>
Customer.cs(模型):
using System.ComponentModel;
namespace TestMvvm444.Model
{
class Customer : INotifyPropertyChanged
{
public int ID { get; set; }
public int NumberOfContracts { get; set; }
private string firstName;
private string lastName;
public string FirstName
{
get { return firstName; }
set
{
if (firstName != value)
{
firstName = value;
RaisePropertyChanged("FirstName");
RaisePropertyChanged("FullName");
}
}
}
public string LastName
{
get { return lastName; }
set
{
if (lastName != value)
{
lastName = value;
RaisePropertyChanged("LastName");
RaisePropertyChanged("FullName");
}
}
}
public string FullName
{
get { return firstName + " " + lastName; }
}
#region PropertChanged Block
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
#endregion
}
}