Change Notification in MVVM Hierarchies

前端 未结 5 1272
清酒与你
清酒与你 2021-02-01 07:29

Let\'s say in some abstract ViewModel base-class I have a plain-old property as follows:

public Size Size
{
    get { return _size; }
    set
    {
        _size         


        
相关标签:
5条回答
  • 2021-02-01 07:58

    I recently blogged about this exact problem. I include a [DependsUpon("Size")] attribute with the Rectangle. I REALLY like this approach, because it keeps the dependency knowledge with the code that creates the dependency, not the other way around.

    Take a look: http://houseofbilz.com/archive/2009/11/14/adventures-in-mvvm----dependant-properties-with-inotifypropertychanged.aspx

    0 讨论(0)
  • 2021-02-01 07:59

    I use Josh Smith's PropertyObserver, which you can get from his MVVM Foundation library at http://mvvmfoundation.codeplex.com/.

    Usage:

    _viewmodel_observer = new PropertyObserver<OtherViewModel>(_OtherViewModel)
       .RegisterHandler(m => m.Size, m => RaisePropertyChanged(Rectangle);
    

    Brian's attribute approach is nice too. One thing I like about PropertyObserver is that I can execute arbitrary code; allowing me to check conditions which may make me avoid the raise or perform other actions all together.

    0 讨论(0)
  • 2021-02-01 08:00

    maybe because im a VB guy, but in your Rectangle code it looks like you are accessing the private _size declaration instead of the Public Size property which would not fire the OnPropertyChanged event to alert the view.

    Also I may be off base, but shouldnt Rectangle be an actual Object while Size is a property of that object? Maybe that is what you are doing..some C# methodologies are still really foreign to me.

    0 讨论(0)
  • 2021-02-01 08:11

    You can simply override OnPropertyChanged in the derived ViewModel like so:

    protected override void OnPropertyChanged(string propertyName) {
        base.OnPropertyChanged(propertyName);
        if (propertyName == "Size") {
            base.OnPropertyChanged("Rectangle");
        }
    }
    

    Another possibility... A while back I put together a pretty nice ViewModel base class that supports attributes on properties like:

    [DependsOn("Size")]
    public Rect Rectangle {
        get { new Rect(0,0,Size.Width, Size.Height); }
    }
    

    Then the ViewModel base class collects these DependsOnAttribute's at runtime and in its OnPropertyChanged method it basically just looks to see what other properties need to be invalidated when a property change occurs.

    0 讨论(0)
  • 2021-02-01 08:14

    A clean MVVM way would be to use a Messenger subscribe/notify mechanism (like in Josh Smith's MvvmFoundation)

    Create a singleton Messenger object somewhere - the main App class is always a good place for this

    public partial class App : Application
    {
        private static Messenger _messenger;
        public static Messenger Messenger
        {
            get
            {
                if (_messenger == null)
                {
                    _messenger = new Messenger();
                }
                return _messenger;
            }
        }
    }
    

    In the Size setter from the base class, notify changes:

    public Size Size
    {
        get { return _size; }
        set
        {
            _size = value;
            OnPropertyChanged("Size");
    
            App.Messenger.NotifyColleagues("SIZE_CHANGED");
        }
    }
    

    Now you can let your inherited ViewModel's listen for these changes, and raise PropertyChanged events as appropriate...

    public MyViewModel : MyViewModelBase
    {
        public MyViewModel()
        {
            App.Messenger.Register("SIZE_CHANGED", () => OnPropertyChanged("Rectangle"));
        }
    }
    

    Of course - you can add as many subscriptions to this message as you need - one for each property that needs changes to be notified back to the View...

    Hope this helps :)

    0 讨论(0)
提交回复
热议问题