繁体   English   中英

事件,使用这些事件的方法和继承

[英]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作为SampleViewModelDataContext ,它SampleUserControlDependencyProperty

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 )。

为了同步这三个值,我添加了TextPropertyChangedCallbackViewModel_PropertyChanged方法,它们更新了需要更新的字段。

上面的代码可以正常工作,并且上面提到的三个位置都保持最新,事件发生等,当使用SampleUsercontrol进行数据绑定时,一切都很好。

但是SampleViewModel会触发事件BaseViewModel.PropertyChanged ,并且由于打算广泛使用BaseViewModel ,因此我希望每个ViewModel都有自己的事件PropertyChanged ,至少是为了避免事件重叠。

所以我取消的代码SampleViewModel从而重新定义了事件PropertyChanged ,但它打破了该领域之间的同步Name的实例SampleViewModel和财产TextPropertySampleUserControl

我在构思方面犯了一些错误吗? 您对我有什么指导吗? 为每个继承自BaseViewModel ViewModel定义不同事件PropertyChanged的最佳经济方法是什么,同时仍使用该基类中定义的通用方法(此类方法使用PropertyChanged )? (我想避免要粘贴大量代码。)

我知道更多的是关于优化的,但是这种优化可以在速度较慢的软件和速度较快的软件之间产生区别。 我处于代码分解的阶段,因此我喜欢形状优美,优雅且分解的代码。

一天结束了,我可能会错过一些明显的解决方案。

预先感谢您提供任何线索,朱利安

TL; DR:基本上,我会仔细检查您是否在该用户控件上正确执行了DC / DP,并抛出了PropertyChanged多个定义的任何概念

详细:

  1. 您在基类中定义了PropertyChanged ,这很棒。 没有理由其他任何地方重新定义它 确实,您只是在通过这样做自找麻烦。
  2. 与此相关的是,您实际上应该仅创建一种方法来执行事件调用,而不要执行setter中的整个handler 减少复制粘贴。
  3. 您必须使用TextPropertyChanged的事实在这里是一个巨大的 TextPropertyChanged信号。 与真正的问题有关,您可能正在滥用依赖项属性。 DP用于允许控件绑定到用户控件的属性。 通常,您不会将它们与控件内部的数据上下文一起使用,因为如您所见,保持它们同步是一场噩梦。
  4. 通常,如果将用户控件设置为与任何其他控件(例如,子视图)区分开,则它们仅应具有自己的数据上下文。 如果它们只是一个花哨的控件,那么给他们一个视图模型几乎不会给您任何帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM