C# 事件、使用这些事件的方法和继承
我正在创建一个在WPF中开发的软件的程序端架构,我设计的架构符合MVVM模式 出于许多原因(设计、一致性、可重用性、可维护性、可伸缩性等),我创建了类C# 事件、使用这些事件的方法和继承,c#,wpf,mvvm,C#,Wpf,Mvvm,我正在创建一个在WPF中开发的软件的程序端架构,我设计的架构符合MVVM模式 出于许多原因(设计、一致性、可重用性、可维护性、可伸缩性等),我创建了类BaseViewModel,实现接口INotifyPropertyChanged和一些其他方法: public class BaseViewModel: INotifyPropertyChanged { private PropertyChangedEventHandler property_changed; public even
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
,它显示了一个dependencProperty
:
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
的属性内(此属性文本
通过绑定
与视图模型
的名称
字段双向绑定)
为了同步这三个值,我添加了方法TextPropertyChangedCallback
和ViewModel\u PropertyChanged
,用于更新需要更新的字段
上面的代码可以工作,上面提到的三个位置保持最新,事件触发等等,当数据绑定使用SampleUsercontrol
时,一切正常
但是SampleViewModel
触发事件BaseViewModel.PropertyChanged
,并且由于BaseViewModel
被广泛使用,我希望每个ViewModel
都有自己的事件PropertyChanged
,至少为了避免事件重叠
因此,我取消了对SampleViewModel
的代码的注释,从而重新定义了事件PropertyChanged
,但它破坏了SampleViewModel
实例的Name
字段与SampleUserControl
的TextProperty
属性之间的同步
我在构思方面是否犯了一些错误?
你对我有什么指导吗?
对于继承自BaseViewModel
的每个ViewModel,定义不同事件PropertyChanged
的最佳经济方式是什么,同时仍然使用该基类中定义的通用方法(此类方法使用PropertyChanged
)?
(我希望避免复制粘贴大量代码。)
我知道这更多的是关于优化,但是这样的优化可以在慢软件和快软件之间产生区别。我正处于代码分解阶段,所以我喜欢形状优美、优雅且经过分解的代码
最后,我可能会错过一些显而易见的解决方案
提前感谢您提供的任何线索,
JulienTL;DR:基本上,我会再次检查您是否在该用户控件上正确执行DC/DP,并抛弃任何关于
属性更改的多个定义的概念
详细内容:
您在基类中定义了PropertyChanged
,这很好。没有理由在任何其他地方重新定义它。。实际上,这样做只是自找麻烦
与此相关的是,您实际上应该只创建一个方法来执行事件调用,而不是在setter.Insta中执行整个处理程序位来减少复制粘贴
您必须使用TextPropertyChanged
这一事实在这里是一个巨大的危险信号。这与实际问题有关,即您可能正在滥用依赖项属性。DPs用于允许父控件绑定到用户控件的属性。您通常不会将它们与用户控件内部的数据上下文结合使用e控制,因为正如您所看到的,保持它们的同步是一场噩梦
一般来说,如果用户控件被设置为独立于任何其他控件(即子视图),那么用户控件应该只有自己的数据上下文。如果用户控件只是一个花哨的控件,那么给它们一个视图模型很难得到任何东西
1.不同意。我不希望对实际上是横切关注点的东西进行继承,尝试对INPC
使用AOP(请参见PropertyChanged.Fody)@Aron那很好,如果你不想要一个基础视图模型,我不会和你争论。也就是说,你不应该在基础类和派生类中都定义它,因为基础类会被隐藏,并可能会给你带来各种奇怪的问题。你说的“TL”、“DR”和“DC/DP”是什么意思?第2点是什么意思?(可能我已经在上面提到的方法中实现了它,但没有显示。)关于第3点和第4点,我有我的理由,噩梦对我来说已经结束了,因为事情与上面的代码是同步的。关于第1点,我已经告诉过每个ViewModel有一个事件可以帮助我管理事件,而接受这个挑战是本文的目的。我不知道如何构思事件管理器否则,@JulienFertéTL;DR“=”太长,没有阅读”.DC=DataContext,DP=DependencyProperty。在第二个方面,我是说你的属性设置器中有一些样板文件,关于你对第1点、第3点和第4点的响应,可以放在一个方法中。事实上,你做错了,让它工作了,并且发现了这种方法的一些问题,这应该告诉你改变你做这件事的方式。All你现在的做法是积累技术债务。我做错了什么?做我现在做的事情的更好方法是什么?