我有一些依赖于设置的两个属性的逻辑,因为当两个属性都有值时,它就会执行。例如:
private void DoCalc() {
if (string.IsNullOrEmpty(Property1) || string.IsNullOrEmpty(Property2))
return;
Property3 = Property1 + " " + Property2;
}每次更改Property1或Property2时都需要执行该代码,但我很难弄清楚如何以一种在风格上可接受的方式来执行它。以下是我所看到的选择:
1)从ViewModel调用方法
我对此在概念上没有问题,因为逻辑仍然在ViewModel中-我不是一个“不隐藏代码”的纳粹分子。然而,“触发器”逻辑(当任何一个属性改变时)仍然在UI层,这是我不喜欢的。代码幕后将如下所示:
void ComboBox_Property1_SelectedItemChanged(object sender, RoutedEventArgs e) {
viewModel.DoCalc();
}2)从属性设置器调用方法
这种方法看起来最“纯粹”,但它看起来也很丑陋,似乎逻辑是隐藏的。它看起来像这样:
public string Property1 {
get {return property1;}
set {
if (property1 != value) {
property1 = value;
NotifyPropertyChanged("Property1");
DoCalc();
}
}
}3)钩入PropertyChanged事件
我现在认为这可能是正确的方法,但在实现视图模型中挂钩属性更改事件感觉很奇怪。它看起来像这样:
public ViewModel() {
this.PropertyChanged += new PropertyChangedEventHandler(ViewModel_PropertyChanged);
}
void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e) {
if (e.PropertyName == "Property1" || e.PropertyName == "Property2") {
DoCalc();
}
}因此,我的问题是,如果您正在浏览一些具有该需求的源代码,您更希望看到实现哪种方法(以及为什么?)感谢您的任何意见。
发布于 2010-03-14 10:29:00
我不认为在二传手中做这件事很丑陋...实际上,这可能是您提到的3种方法中最好的一种,因为当您阅读代码时,您会立即看到更改Property1或Property2的值将重新计算Property3;对于其他两种方法,这一点并不明显。
但是,我不会使用这两个选项。根据Property1和Property2的说法,我认为更好的方法是将Property3设为只读,然后在getter中计算它的值:
public string Property3
{
get { return Property3 = Property1 + " " + Property2; }
}这样,在Property1和Property2的setter方法中,您也只需要为Property3调用NotifyPropertyChanged。
发布于 2010-03-17 02:20:35
(2)是我通常的做法。
也就是说,这让我想知道是否有另一种方法可以使用Rx框架来做这类事情:http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx
这就是我想出来的(警告-不要这样做!);
public class ViewModel : INotifyPropertyChanged
{
public ViewModel()
{
var o1 =
Observable.FromEvent<PropertyChangedEventArgs>(this, "PropertyChanged");
o1.Subscribe(e => Debug.WriteLine(e.EventArgs.PropertyName));
var o2 = o1.SkipWhile(e => e.EventArgs.PropertyName != "Property1");
var o3 = o1.SkipWhile(e => e.EventArgs.PropertyName != "Property2");
var o4 = o1.SkipWhile(e => e.EventArgs.PropertyName != "Result");
var o5 = Observable.CombineLatest(o2, o3, (e1, e2) => DoStuff()).TakeUntil(o4);
o5.Subscribe(o => Debug.WriteLine("Got Prop1 and Prop2"));
}
public string DoStuff()
{
return Result = string.Concat(Property1, Property2);
}
private string _property1;
public string Property1
{
get { return _property1; }
set
{
_property1 = value;
OnNotifyPropertyChanged("Property1");
}
}
private string _property2;
public string Property2
{
get { return _property2; }
set
{
_property2 = value;
OnNotifyPropertyChanged("Property2");
}
}
private string _result;
public string Result
{
get { return _result; }
set
{
_result = value;
OnNotifyPropertyChanged("Result");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnNotifyPropertyChanged(string name)
{
var handler = PropertyChanged;
if(handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}发布于 2010-03-14 15:07:03
是的,@Thomas是对的。方法2是WPF环境中的完美方法。假设您已将ListBox.SelectedValue TwoWay绑定添加到Property1
您的(1)是无效的,因为这会将业务逻辑暴露到视图中。(3)是一个不必要的事件处理,无论如何都是由Property1设置器代码触发的。所以最好直接从Setter调用它。所以MVVM方式是(2)
https://stackoverflow.com/questions/2440296
复制相似问题