/// <summary> /// Watches the specified source. /// </summary> /// <param name="source"> /// The source. /// </param> /// <param name="property"> /// The property. /// </param> /// <returns> /// The <see cref="WeakCommandBinding"/>. /// </returns> /// <exception cref="System.ArgumentNullException"> /// The source can not be null. /// </exception> public WeakCommandBinding Watch(object source, string property) { if (source == null) { throw new ArgumentNullException("source"); } var bindContext = new BindContext(source, property); var entry = new WeakEntry(null, bindContext.Source, property); WeakEvent watchEvent; if (this.watchEvents.ContainsKey(entry)) { watchEvent = this.watchEvents[entry]; } else { watchEvent = new WeakEvent(this); this.watchEvents.Add(entry, watchEvent); } string propertyName = property.Contains(".") ? property.Right(".") : property; watchEvent.AttachEvent( bindContext, WeakPropertyBinding.PropertyChangedEventName, WatchEventCallbackMethod, (o, args) => string.Equals(((PropertyChangedEventArgs)args).PropertyName, propertyName)); this.RaiseCanExecuteChanged(); return(this); }
public void Test_WeakBindEvent_NormalProperty() { var viewModel = new TestViewModel(); var view = new TestView(); var propertyBinding = new WeakPropertyBinding(view, "Text1", viewModel, "Name") .Initialize<WeakPropertyBinding>(); var weakEvent = new WeakEvent(viewModel); Assert.IsFalse(weakEvent.IsAttached); }
/// <summary> /// Detaches the source. /// </summary> /// <param name="source"> /// The source. /// </param> protected override void DetachSource(object source) { base.DetachSource(source); if (source != null && source.GetType().ContainsEvent(WeakCollectionBinding.CollectionChangedEventName)) { if (collectionWeakEvent != null) { collectionWeakEvent.DetachEvent(); collectionWeakEvent = null; } } }
/// <summary> /// Attaches the source. /// </summary> /// <param name="source"> /// The source. /// </param> protected override void AttachSource(object source) { base.AttachSource(source); if (source != null && source.GetType().ContainsEvent(WeakCollectionBinding.CollectionChangedEventName)) { if (collectionWeakEvent != null) { collectionWeakEvent.DetachEvent(); } if (collectionWeakEvent == null) { collectionWeakEvent = new WeakEvent(this); } collectionWeakEvent.AttachEvent(source, null, WeakCollectionBinding.CollectionChangedEventName, "OnSourceCollectionChanged"); } }
/// <summary> /// UnWatch the source property. /// </summary> /// <param name="source"> /// The source. /// </param> /// <param name="property"> /// The property. /// </param> /// <returns> /// The <see cref="WeakCommandBinding"/>. /// </returns> /// <exception cref="System.ArgumentNullException"> /// The source can not be null. /// </exception> public WeakCommandBinding UnWatch(object source, string property) { if (source == null) { throw new ArgumentNullException("source"); } var bindSource = new BindContext(source, property); var entry = new WeakEntry(null, bindSource.Source, property); if (this.watchEvents.ContainsKey(entry)) { WeakEvent watchEvent = this.watchEvents[entry]; watchEvent.DetachEvent(); this.watchEvents.Remove(entry); } this.RaiseCanExecuteChanged(); return(this); }
/// <summary> /// Initializes a new instance of the <see cref="WeakCommandBinding"/> class. /// </summary> /// <param name="target"> /// The target. /// </param> /// <param name="targetProperty"> /// The target property. /// </param> /// <param name="source"> /// The source. /// </param> /// <param name="sourceProperty"> /// The source property. /// </param> public WeakCommandBinding(object target, string targetProperty, object source, string sourceProperty) : base(target, targetProperty, source, sourceProperty) { this.commandCanExecuteEvent = new WeakEvent(this); }
public void Test_MemoryLeak_WeakEvent() { // 1. Normal Event will hold the strong reference which prevent the GC collect. var view = new TestView(); var viewModel = new TestViewModel(); var reference = new WeakReference(view); viewModel.TestViewModelEvent += view.OnEventOccured; viewModel.RaiseTestViewModelEvent(); Assert.AreEqual(1, view.EventCount); Assert.AreEqual(1, viewModel.GetTestViewModelEventInvocationCount()); view = null; GC.Collect(); Assert.IsTrue(reference.IsAlive); // Still live viewModel.TestViewModelEvent -= reference.GetTarget<TestView>().OnEventOccured; GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); Assert.IsFalse(reference.IsAlive); reference = null; Assert.IsNull(reference.GetTarget<TestView>()); // 2. WeakEvent hold the weak reference which will not prevent GC collect. var view2 = new TestView(); var viewModel2 = new TestViewModel(); var reference2 = new WeakReference(view2); var weakEvent = new WeakEvent(view2); weakEvent.AttachEvent(viewModel2, null, "TestViewModelEvent", "OnEventOccured"); viewModel2.RaiseTestViewModelEvent(); Assert.AreEqual(1, view2.EventCount); view2 = null; GC.Collect(); Assert.IsFalse(reference2.IsAlive); viewModel2.RaiseTestViewModelEvent(); Assert.AreEqual(0, viewModel2.GetTestViewModelEventInvocationCount()); }