using System; using System.Collections.Generic; using System.ComponentModel; using System.Windows; using System.Windows.Controls; using Caliburn.Services; using Caliburn.StateManagement; namespace Caliburn.StateManagement { public class UIState : IPersistable { #region Fields protected readonly Dictionary _values = new Dictionary(); protected WeakReference _target; private bool _isRestoring = false; #endregion #region IPersistable Members public virtual void Write(StateWriter writer) { foreach (KeyValuePair pair in _values) { writer.AddValue(pair.Key, pair.Value); } } public virtual void Read(StateContainer state) { foreach (StateEntry child in state.Children) { ValueEntry entry = (ValueEntry)child; _values[entry.Key] = entry.Value; } RestoreTarget(); } #endregion #region Helper Methods protected virtual void RestoreTarget() { if (_target != null) { object actualTarget = _target.Target; if (actualTarget != null) { _isRestoring = true; foreach (KeyValuePair pair in _values) { RestoreProperty(actualTarget, pair.Key, pair.Value); } _isRestoring = false; } } } protected virtual void Target_PropertyChanged(object sender, DependencyProperty property) { if (_isRestoring) return; DependencyObject dp = (DependencyObject)sender; _values[property.Name] = dp.GetValue(property); } protected virtual void RestoreProperty(object actualTarget, string property, object value) { actualTarget.GetType().GetProperty(property).SetValue(actualTarget, value, null); } #endregion #region Statics public static void Track(string key, DependencyObject target, IList properties) { IShellState state = DI.Resolve(); UIState uiState = state.GetValue(key); if (uiState == null) { uiState = new UIState(); state.SetValue(key, uiState); } uiState._target = new WeakReference(target); uiState._isRestoring = true; foreach (DependencyProperty property in properties) { object value; DependencyProperty theProperty = property; if (uiState._values.TryGetValue(property.Name, out value) && value != null) { uiState.RestoreProperty(target, property.Name, value); } else uiState._values[property.Name] = null; DependencyPropertyDescriptor .FromProperty(property, target.GetType()) .AddValueChanged(target, delegate(object sender, EventArgs e) { uiState.Target_PropertyChanged(sender, theProperty); }); } uiState._isRestoring = false; } public static void RegisterTrackingDetails(Type type, params DependencyProperty[] properties) { List details = new List(); foreach (DependencyProperty property in properties) { details.Add(property); } _trackingDetails[type] = details; } public static readonly DependencyProperty TrackingKeyProperty = DependencyProperty.RegisterAttached( "TrackingKey", typeof(string), typeof(UIState), new PropertyMetadata(TrackingKeyChanged) ); public static void SetTrackingKey(DependencyObject d, string key) { if(d is Window) Track(key, d, _trackingDetails[typeof(Window)]); else Track(key, d, _trackingDetails[d.GetType()]); } private static void TrackingKeyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (e.NewValue != e.OldValue && e.NewValue != null) SetTrackingKey(d, e.NewValue.ToString()); } private static IDictionary> _trackingDetails = new Dictionary> { { typeof(Window), new List { Window.LeftProperty, Window.TopProperty, Window.WidthProperty, Window.HeightProperty, Window.WindowStateProperty } }, { typeof(Expander), new List { Expander.IsExpandedProperty } }, { typeof(Slider), new List { Slider.ValueProperty } } }; #endregion } }