[英]Events, methods using these events and inheritance
我正在创建使用WPF开发的软件的程序端体系结构,并且将该体系结构设计为符合MVVM模式。
出于许多原因(设计,一致性,可重用性,可维护性,可伸缩性等),我创建了实现接口INotifyPropertyChanged
和其他方法的BaseViewModel
类:
public class BaseViewModel: INotifyPropertyChanged
{
private PropertyChangedEventHandler property_changed;
public event PropertyChangedEventHandler PropertyChanged
{
add { property_changed += value; }
remove { property_changed -= value; }
}
//Here several methods using PropertyChanged and easing the usage of ViewModels
public BaseViewModel() { }
}
上面定义的类BaseViewModel
用作应用程序的所有其他ViewModel
的基类(或者至少是这样),例如:
public class SampleViewModel : BaseViewModel
{
//private PropertyChangedEventHandler property_changed;
//public event PropertyChangedEventHandler PropertyChanged
//{
// add { property_changed += value; }
// remove { property_changed -= value; }
//}
public String Name
{
get { return name; }
set
{
if(value != name)
{
name = value;
var handler = PropertyChanged;
if(handler != null)
{
handler(this, new PropertyChangedEventArgs("Name"));
}
}
}
}
private String name = "";
public SampleViewModel ()
: base() { }
}
我使用类SampleViewModel
作为SampleViewModel
的DataContext
,它SampleUserControl
了DependencyProperty
:
public partial class SampleUserControl : UserControl
{
#region ViewModel
public SampleViewModel ViewModel
{
get { return view_model; }
}
private SampleViewModel view_model = new SampleViewModel();
#endregion
#region DependencyProperty
public String Text
{
get { return (String)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(String), typeof(SampleUserControl),
new FrameworkPropertyMetadata(String.Empty, FrameworkPropertyMetadataOptions.AffectsRender,
new PropertyChangedCallback(TextPropertyChangedCallback)));
private static void TextPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
SampleUserControl sender = d as SampleUserControl;
if (sender != null)
{
sender.ViewModel.Name = (String)e.NewValue;
}
}
#endregion
public SampleUserControl()
{
InitializeComponent();
LayoutRoot.DataContext = ViewModel;
ViewModel.PropertyChanged += new PropertyChangedEventHandler(ViewModel_PropertyChanged);
}
void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
SampleViewModel viewmodel = sender as SampleViewModel;
if (viewmodel != null)
{
switch (e.PropertyName)
{
case "Name":
SetValue(TextProperty, viewmodel.Name);
break;
default:
break;
}
}
}
}
总而言之,与SampleUserControl
有关的数据包含在三个位置: SampleViewModel
的实例,位于TextProperty
和位于SampleUserControl
的xaml部分中的TextBox
属性Text
中(此属性Text
是通过Binding
与字段Name
双向Binding
的)的ViewModel
)。
为了同步这三个值,我添加了TextPropertyChangedCallback
和ViewModel_PropertyChanged
方法,它们更新了需要更新的字段。
上面的代码可以正常工作,并且上面提到的三个位置都保持最新,事件发生等,当使用SampleUsercontrol
进行数据绑定时,一切都很好。
但是SampleViewModel
会触发事件BaseViewModel.PropertyChanged
,并且由于打算广泛使用BaseViewModel
,因此我希望每个ViewModel
都有自己的事件PropertyChanged
,至少是为了避免事件重叠。
所以我取消的代码SampleViewModel
从而重新定义了事件PropertyChanged
,但它打破了该领域之间的同步Name
的实例SampleViewModel
和财产TextProperty
的SampleUserControl
。
我在构思方面犯了一些错误吗? 您对我有什么指导吗? 为每个继承自BaseViewModel
ViewModel定义不同事件PropertyChanged
的最佳经济方法是什么,同时仍使用该基类中定义的通用方法(此类方法使用PropertyChanged
)? (我想避免要粘贴大量代码。)
我知道更多的是关于优化的,但是这种优化可以在速度较慢的软件和速度较快的软件之间产生区别。 我处于代码分解的阶段,因此我喜欢形状优美,优雅且分解的代码。
一天结束了,我可能会错过一些明显的解决方案。
预先感谢您提供任何线索,朱利安
TL; DR:基本上,我会仔细检查您是否在该用户控件上正确执行了DC / DP,并抛出了PropertyChanged
多个定义的任何概念
详细:
PropertyChanged
,这很棒。 没有理由在其他任何地方重新定义它 。 确实,您只是在通过这样做自找麻烦。 handler
。 减少复制粘贴。 TextPropertyChanged
的事实在这里是一个巨大的 TextPropertyChanged
信号。 与真正的问题有关,您可能正在滥用依赖项属性。 DP用于允许父控件绑定到用户控件的属性。 通常,您不会将它们与控件内部的数据上下文一起使用,因为如您所见,保持它们同步是一场噩梦。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.