事件,使用这些事件的方法和继承
本文关键字:事件 方法 继承 | 更新日期: 2023-09-27 18:08:03
我正在创建一个用WPF开发的软件的程序端体系结构,我设计的体系结构符合MVVM模式。
出于多种原因(设计、一致性、可重用性、可维护性、可伸缩性等),我创建了类BaseViewModel
,实现了接口INotifyPropertyChanged
和其他一些方法:
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
作为SampleUserControl
的DataContext
,它具有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
与ViewModel
的字段Name
双向绑定)。
为了同步这三个值,我添加了TextPropertyChangedCallback
和ViewModel_PropertyChanged
方法,它们更新需要更新的字段。
上面的代码可以工作,并且上面提到的三个位置保持最新,事件触发等等,当SampleUsercontrol
与数据绑定一起使用时,一切都很好。
但是SampleViewModel
触发事件BaseViewModel.PropertyChanged
,并且由于BaseViewModel
意味着被广泛使用,我希望每个ViewModel
都有自己的事件PropertyChanged
,至少为了避免重叠事件。
所以我取消了SampleViewModel
的注释,从而重新定义了事件PropertyChanged
,但是它破坏了SampleViewModel
实例的字段Name
和SampleUserControl
的属性TextProperty
之间的同步。
我是否在构思方面犯了一些错误?你能给我一些指导吗?为继承BaseViewModel
的每个ViewModel定义不同的事件PropertyChanged
,同时仍然使用该基类中定义的通用方法(此类方法使用PropertyChanged
)的最佳经济方法是什么?(我希望避免有大量的代码需要复制粘贴。)
我知道这更多的是关于优化,但是这样的优化可以使一个慢的软件和一个快的软件之间的差异。我正处于代码分解的阶段,所以我喜欢形状漂亮、优雅、分解的代码。
一天结束了,我可能会错过一些明显的解决方案。
提前感谢任何线索,朱利安
TL;DR:基本上,我会仔细检查您是否正确地在用户控件上执行DC/DP,并抛弃任何PropertyChanged
多重定义的概念
- 您在基类中定义了
PropertyChanged
,这很棒。没有理由在 else的任何地方重新定义它。真的,你这样做是在自找麻烦。 与此相关的是,你应该真的只是做一个方法来做事件调用,而不是在setter中做整个 - 事实上,你不得不使用
TextPropertyChanged
是一个巨大的危险信号。这涉及到真正的问题,你可能正在滥用你的依赖属性。dp用于允许父控件绑定到用户控件的属性。通常不会将它们与控件内部的数据上下文结合使用,因为正如您所看到的,保持它们同步是一场噩梦。 - 一般来说,如果用户控件被设置为与任何其他控件(即子视图)分开,则用户控件应该只有自己的数据上下文。如果它们只是一个花哨的控件,那么给它们一个视图模型很少给你任何东西。
handler
位。复制粘贴的还原。