簡體   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