我正在编写一个带有大规模数据模型的应用程序 - 作为其中的一部分,我第一次使用MVVM模式.有很多用于管理各种实体的屏幕,因此有很多视图模型.我发现每个视图模型都将我正在使用的POCO实体的每个属性包装在依赖项属性中,这样我就可以将它绑定到编辑器字段,然后在用户提交更改时将其写回实体.这对我来说感觉就像是一大堆额外的腿部工作,我不禁想知道我是否错过了这一点,或者是否有更简单的方法来实现我的目标.举个例子,我有一个地址视图模型:
public class AddressViewModel : EntityViewModel<Address>
{
#region Properties
public string AddressLine1
{
get { return (string) GetValue(AddressLine1Property); }
set { SetValue(AddressLine1Property, value); }
}
// Using a DependencyProperty as the backing store for AddressLine1. This enables animation, styling, binding, etc...
public static readonly DependencyProperty AddressLine1Property =
DependencyProperty.Register("AddressLine1", typeof (string), typeof (AddressViewModel), new PropertyMetadata(string.Empty, HandleAddressChange));
private static void HandleAddressChange(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var vm = d as AddressViewModel;
if (vm != null)
{
vm.OnPropertyChanged(AddressAsSingleLineStringPropertyName);
}
}
public string AddressLine2
{
get { return (string) GetValue(AddressLine2Property); }
set { SetValue(AddressLine2Property, value); }
}
// Using a DependencyProperty as the backing store for AddressLine2. This enables animation, styling, binding, etc...
public static readonly DependencyProperty AddressLine2Property =
DependencyProperty.Register("AddressLine2", typeof (string), typeof (AddressViewModel), new PropertyMetadata(string.Empty));
public string AddressLine3
{
get { return (string) GetValue(AddressLine3Property); }
set { SetValue(AddressLine3Property, value); }
}
// Using a DependencyProperty as the backing store for AddressLine2. This enables animation, styling, binding, etc...
public static readonly DependencyProperty AddressLine3Property =
DependencyProperty.Register("AddressLine3", typeof (string), typeof (AddressViewModel), new PropertyMetadata(string.Empty));
public string AddressLine4
{
get { return (string) GetValue(AddressLine4Property); }
set { SetValue(AddressLine4Property, value); }
}
// Using a DependencyProperty as the backing store for AddressLine2. This enables animation, styling, binding, etc...
public static readonly DependencyProperty AddressLine4Property =
DependencyProperty.Register("AddressLine4", typeof (string), typeof (AddressViewModel), new PropertyMetadata(string.Empty));
public string AddressLine5
{
get { return (string) GetValue(AddressLine5Property); }
set { SetValue(AddressLine5Property, value); }
}
// Using a DependencyProperty as the backing store for AddressLine2. This enables animation, styling, binding, etc...
public static readonly DependencyProperty AddressLine5Property =
DependencyProperty.Register("AddressLine5", typeof (string), typeof (AddressViewModel), new PropertyMetadata(string.Empty));
public string PostCode
{
get { return (string) GetValue(PostCodeProperty); }
set { SetValue(PostCodeProperty, value); }
}
// Using a DependencyProperty as the backing store for PostCode. This enables animation, styling, binding, etc...
public static readonly DependencyProperty PostCodeProperty =
DependencyProperty.Register("PostCode", typeof (string), typeof (AddressViewModel), new PropertyMetadata(string.Empty, HandleAddressChange));
/// <summary>
/// Gets a value indicating whether this instance is valid for save.
/// </summary>
/// <value> <c>true</c> if this instance is valid for save; otherwise, <c>false</c> . </value>
/// <exception cref="System.NotImplementedException"></exception>
public override bool IsValidForSave
{
get { return !string.IsNullOrWhiteSpace(AddressLine1); }
}
/// <summary>
/// Gets a value indicating whether this instance is valid for edit.
/// </summary>
/// <value> <c>true</c> if this instance is valid for edit; otherwise, <c>false</c> . </value>
public override bool IsValidForEdit
{
get { return true; }
}
#endregion
#region Constructor
/// <summary>
/// Initializes a new instance of the <see cref="AddressViewModel" /> class.
/// </summary>
public AddressViewModel(Address address) : base(address)
{
}
#endregion
#region Private Methods
/// <summary>
/// Sets the properties from entity.
/// </summary>
public override void SetPropertiesFromEntity()
{
AddressLine1 = Entity.AddressLine1;
AddressLine2 = Entity.AddressLine2;
AddressLine3 = Entity.AddressLine3;
AddressLine4 = Entity.AddressLine4;
AddressLine5 = Entity.AddressLine5;
PostCode = Entity.PostCode;
}
/// <summary>
/// Sets the entity from properties.
/// </summary>
public override void SetEntityFromProperties()
{
Entity.AddressLine1 = AddressLine1;
Entity.AddressLine2 = AddressLine2;
Entity.AddressLine3 = AddressLine3;
Entity.AddressLine4 = AddressLine4;
Entity.AddressLine5 = AddressLine5;
Entity.PostCode = PostCode;
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个简单的五个属性实体的包装.
将此与MVC Web应用程序的腿部工作相比较,我只是为该模型生成一个编辑器,并且我们在开销方面存在相当严重的差异,因此我可以双向绑定一堆文本框.我更愿意有人告诉我,我已经错过了这一点,并且我完全错误地做了这一点,但据我所知,我的实体是我的模型,viewmodel包装它,视图绑定到viewmodel.我查看了MVVM框架,但它们似乎更倾向于帮助控制程序流并管理视图集和视图模型,而不是减少创建视图模型的工作量.
您根本不需要这些DependencyProperties.我建议你将它们作为标准属性实现.
如果您的viewmodel可能在显示UI时发生更改,并且您希望该更改反映在UI中,则需要实现该INotifyPropertyChanged界面.您可以使用Fody PropertyChanged库(可通过Nuget获得)轻松完成此操作,如果您只是为类添加属性,它将为您完成所有的工作.
您真正需要依赖项属性的唯一情况是,是否在Xaml中设置了该属性的值,并且您希望使用a MarkupExtension(例如,使用Binding或x:Static)设置该值.在你的情况下,你将绑定应用于控件上的属性(我猜Textbox.Text),所以它TextBox.Text就是一个DependencyProperty.
虽然我并不完全清楚你的代码究竟想要实现什么,但我相信在这种情况下你不需要依赖属性,而只需要普通属性(可能还有INotifyPropertyChanged接口).在创建控件时,将使用依赖项属性,其中该控件的属性将绑定到视图模型中的属性.如果您只是尝试将视图模型绑定到现有控件,那么只需要简单的属性.
| 归档时间: |
|
| 查看次数: |
721 次 |
| 最近记录: |