0

I'm currently working on a solution that has a set of composite ViewModels that are mapped from domain models coming back from a set of data access services.

So far I've had a good amount of success with implementing INotifyPropertyChanged on the base ViewModel object and notifying the UI of changes to the property objects via property changed events.

Here's an example of a view model:

public class DisplayDataModel : INotifyPropertyChanged{ 
   private DateTime _lastRefreshTime;
    public DateTime LastRefreshTime {
        get { return _lastRefreshTime; }
        set {
            _lastRefreshTime = value;
            this.NotifyPropertyChanged(lddm => lddm.LastRefreshTime, PropertyChanged);
        }
    }

    private string _lineStatus;
    public string LineStatus {
        get { return _lineStatus; }
        set {
            if (_lineStatus != value) {
                _lineStatus = value;
                this.NotifyPropertyChanged(lddm => lddm.LineStatus, PropertyChanged);
            }
        }
    }           

    private ProductionBrickModel _productionBrick;
    public ProductionBrickModel ProductionBrick { 
        get { return _productionBrick;}

        set {
            if (_productionBrick != value) {
                _productionBrick = value;
                this.NotifyPropertyChanged(lddm => lddm.ProductionBrick, PropertyChanged);
            }
        }
    }
}

public class ProductionBrickModel{

    public int? Set { get; set; }
    public int? Theoretical { get; set; }
    public int? Actual { get; set; }
    public string LineName { get; set; }
    public TimeSpan? ShiftOverage { get; set; }

    public SolidColorBrush ShiftOverageBrush {
        get {
            if (ShiftOverage.HasValue && ShiftOverage.Value.Milliseconds < 0) {
                return Application.Current.FindResource("IndicatorRedBrush") as SolidColorBrush;
            }

            return Application.Current.FindResource("IndicatorWhiteBrush") as SolidColorBrush;
        }
    }
    public string ShiftOverageString { get { return ShiftOverage.HasValue ? ShiftOverage.Value.ToShortTimeSpanString() : ""; } }

}

So currently I'm firing notification events on the base model and not the production brick property, mostly because the production brick properties will be changing almost every refresh anyways.

Recently I've started cranking refresh times down to around 350ms and I'm seeing situations where the ShiftOverageBrush is changing to white for a split second even though the values are still negative.

My question is by going through and implementing INotifyPropertyChanged on the object types that make up the base view model will I gain any performance, or even possibly solve this issue? Or is this coming from something else entirely that I'm not understanding?

Philter
  • 535
  • 1
  • 9
  • 24

1 Answers1

2

There are two obvious sources of inefficieny in your code:

1) ShiftOverageBrush is using FindResource every time it's called. Why not cache the brushes?

private SolidColorBrush _redBrush;
private SolidColorBrush IndicatorRedBrush
{
    get{ return _redBrush ?? (_redBrush = 
        Application.Current.FindResource("IndicatorRedBrush") as SolidColorBrush)); 
}

... same for white brush

public SolidColorBrush ShiftOverageBrush {
    get {
        if (ShiftOverage.HasValue && ShiftOverage.Value.Milliseconds < 0) {
            return IndicatorRedBrush;
        }

        return IndicatorWhiteBrush;
    }
}

2) Using a lambda expression for NotifyPropertyChanged is convenient but is pretty slow since it uses reflection. If you're cranking up the update rate, then replace the lambdas with strings.

Phil
  • 42,255
  • 9
  • 100
  • 100
  • Good suggestion. The brushes are being used all over in different models so I think I'll make a brush cache class to handle that. That way I can pull brushes from there when necessary. – Philter Mar 21 '13 at 19:26