Index: Core/Common/src/Core.Common.Gui/Forms/PropertyGridView/PropertyGridView.cs =================================================================== diff -u -r6b8f6422c0a6f96f8e563bb6afb82a7a192142b4 -re217c241d1d57575c99e1062b449ea595f9fc764 --- Core/Common/src/Core.Common.Gui/Forms/PropertyGridView/PropertyGridView.cs (.../PropertyGridView.cs) (revision 6b8f6422c0a6f96f8e563bb6afb82a7a192142b4) +++ Core/Common/src/Core.Common.Gui/Forms/PropertyGridView/PropertyGridView.cs (.../PropertyGridView.cs) (revision e217c241d1d57575c99e1062b449ea595f9fc764) @@ -25,7 +25,6 @@ using System.Reflection; using System.Security.Permissions; using System.Windows.Forms; -using Core.Common.Base; using Core.Common.Controls.Views; using Core.Common.Gui.Properties; using Core.Common.Gui.PropertyBag; @@ -35,11 +34,12 @@ /// /// View for displaying the properties of an data object. /// - public class PropertyGridView : PropertyGrid, IView, IObserver + public class PropertyGridView : PropertyGrid, IView { private readonly IPropertyResolver propertyResolver; + private object data; - private IObservable observable; + private IObjectProperties objectProperties; /// /// This delegate enabled asynchronous calls to methods without arguments. @@ -68,19 +68,6 @@ this.propertyResolver = propertyResolver; } - public void UpdateObserver() - { - if (InvokeRequired) - { - ArgumentlessDelegate d = UpdateObserver; - Invoke(d, new object[0]); - } - else - { - Refresh(); - } - } - protected override void OnPropertySortChanged(EventArgs e) { // Needed for maintaining property order (no support for both categorized and alphabetical sorting) @@ -94,11 +81,24 @@ protected override void Dispose(bool disposing) { - observable?.Detach(this); + DisposeObjectProperties(); base.Dispose(disposing); } + private void RefreshPropertyGridView() + { + if (InvokeRequired) + { + ArgumentlessDelegate d = RefreshPropertyGridView; + Invoke(d, new object[0]); + } + else + { + Refresh(); + } + } + #region IView Members public object Data @@ -115,33 +115,34 @@ return; } - DetachObservable(); + DisposeObjectProperties(); data = value; - AttachObservable(); + + SelectedObject = GetObjectProperties(data); + + var dynamicPropertyBag = SelectedObject as DynamicPropertyBag; + objectProperties = dynamicPropertyBag?.WrappedObject as IObjectProperties; + + if (objectProperties != null) + { + objectProperties.RefreshRequired += HandleRefreshRequired; + } } } - private void DetachObservable() + private void DisposeObjectProperties() { - if (observable != null) + if (objectProperties != null) { - observable.Detach(this); - observable = null; + objectProperties.RefreshRequired -= HandleRefreshRequired; + objectProperties.Dispose(); } } - private void AttachObservable() + private void HandleRefreshRequired(object sender, EventArgs e) { - SelectedObject = GetObjectProperties(data); - - var dynamicPropertyBag = SelectedObject as DynamicPropertyBag; - var objectProperties = dynamicPropertyBag?.WrappedObject as IObjectProperties; - if (objectProperties != null) - { - observable = objectProperties.Data as IObservable; - observable?.Attach(this); - } + RefreshPropertyGridView(); } private object GetObjectProperties(object sourceData) Index: Core/Common/src/Core.Common.Gui/PropertyBag/IObjectProperties.cs =================================================================== diff -u -r67284323e2785c651633d9c52049ba12a9c70e6a -re217c241d1d57575c99e1062b449ea595f9fc764 --- Core/Common/src/Core.Common.Gui/PropertyBag/IObjectProperties.cs (.../IObjectProperties.cs) (revision 67284323e2785c651633d9c52049ba12a9c70e6a) +++ Core/Common/src/Core.Common.Gui/PropertyBag/IObjectProperties.cs (.../IObjectProperties.cs) (revision e217c241d1d57575c99e1062b449ea595f9fc764) @@ -19,16 +19,23 @@ // Stichting Deltares and remain full property of Stichting Deltares at all times. // All rights reserved. +using System; + namespace Core.Common.Gui.PropertyBag { /// /// Interface for object properties. /// - public interface IObjectProperties + public interface IObjectProperties : IDisposable { /// /// Gets or sets the data of the object properties. /// object Data { get; set; } + + /// + /// Fired when the property grid should be refreshed. + /// + event EventHandler RefreshRequired; } } \ No newline at end of file Index: Core/Common/src/Core.Common.Gui/PropertyBag/ObjectProperties.cs =================================================================== diff -u -r67284323e2785c651633d9c52049ba12a9c70e6a -re217c241d1d57575c99e1062b449ea595f9fc764 --- Core/Common/src/Core.Common.Gui/PropertyBag/ObjectProperties.cs (.../ObjectProperties.cs) (revision 67284323e2785c651633d9c52049ba12a9c70e6a) +++ Core/Common/src/Core.Common.Gui/PropertyBag/ObjectProperties.cs (.../ObjectProperties.cs) (revision e217c241d1d57575c99e1062b449ea595f9fc764) @@ -19,7 +19,9 @@ // Stichting Deltares and remain full property of Stichting Deltares at all times. // All rights reserved. +using System; using System.ComponentModel; +using Core.Common.Base; namespace Core.Common.Gui.PropertyBag { @@ -29,8 +31,20 @@ /// Type of . public class ObjectProperties : IObjectProperties { + private readonly Observer refreshRequiredObserver; + protected T data; + public event EventHandler RefreshRequired; + + /// + /// Creates a new instance of . + /// + public ObjectProperties() + { + refreshRequiredObserver = new Observer(OnRefreshRequired); + } + [Browsable(false)] public object Data { @@ -41,7 +55,19 @@ set { data = (T) value; + + refreshRequiredObserver.Observable = value as IObservable; } } + + public void Dispose() + { + refreshRequiredObserver?.Dispose(); + } + + private void OnRefreshRequired() + { + RefreshRequired?.Invoke(this, new EventArgs()); + } } } \ No newline at end of file Index: Core/Common/test/Core.Common.Gui.Test/Forms/PropertyGridView/PropertyGridViewTest.cs =================================================================== diff -u -r1bbf51443c907b5f202e80764fa05f2e7f842c04 -re217c241d1d57575c99e1062b449ea595f9fc764 --- Core/Common/test/Core.Common.Gui.Test/Forms/PropertyGridView/PropertyGridViewTest.cs (.../PropertyGridViewTest.cs) (revision 1bbf51443c907b5f202e80764fa05f2e7f842c04) +++ Core/Common/test/Core.Common.Gui.Test/Forms/PropertyGridView/PropertyGridViewTest.cs (.../PropertyGridViewTest.cs) (revision e217c241d1d57575c99e1062b449ea595f9fc764) @@ -22,7 +22,6 @@ using System; using System.Linq; using System.Windows.Forms; -using Core.Common.Base; using Core.Common.Controls.Views; using Core.Common.Gui.Forms.PropertyGridView; using Core.Common.Gui.PropertyBag; @@ -58,7 +57,6 @@ // Assert Assert.IsInstanceOf(propertyGridView); Assert.IsInstanceOf(propertyGridView); - Assert.IsInstanceOf(propertyGridView); Assert.IsNull(propertyGridView.Data); Assert.AreEqual(PropertySort.Categorized, propertyGridView.PropertySort); @@ -153,27 +151,28 @@ } [Test] - public void GivenPropertyGridViewWithObservableSet_WhenNotifyObserverCalled_ThenRefreshTriggered() + public void GivenPropertyGridViewWithObservableSet_WhenRefreshRequiredEventRaised_ThenRefreshTriggered() { // Given var dataObject = new object(); - var observerable = new SimpleObservable(); var mockRepository = new MockRepository(); var objectProperties = mockRepository.Stub(); - objectProperties.Data = observerable; - var propertyResolver = mockRepository.StrictMock(); propertyResolver.Expect(prs => prs.GetObjectProperties(dataObject)).Return(new DynamicPropertyBag(objectProperties)); mockRepository.ReplayAll(); - using (var propertyGridView = new TestGuiPropertyGridView(propertyResolver)) + using (var propertyGridView = new TestGuiPropertyGridView(propertyResolver) { + Data = dataObject + }) + { // When - propertyGridView.Data = dataObject; + objectProperties.Raise(p => p.RefreshRequired += null, + objectProperties, + EventArgs.Empty); // Then - observerable.NotifyObservers(); Assert.AreEqual(1, propertyGridView.RefreshCalled); } mockRepository.VerifyAll(); @@ -213,7 +212,5 @@ base.Refresh(); } } - - private class SimpleObservable : Observable {} } } \ No newline at end of file Index: Core/Common/test/Core.Common.Gui.Test/Forms/PropertyGridView/PropertyResolverTest.cs =================================================================== diff -u -r67284323e2785c651633d9c52049ba12a9c70e6a -re217c241d1d57575c99e1062b449ea595f9fc764 --- Core/Common/test/Core.Common.Gui.Test/Forms/PropertyGridView/PropertyResolverTest.cs (.../PropertyResolverTest.cs) (revision 67284323e2785c651633d9c52049ba12a9c70e6a) +++ Core/Common/test/Core.Common.Gui.Test/Forms/PropertyGridView/PropertyResolverTest.cs (.../PropertyResolverTest.cs) (revision e217c241d1d57575c99e1062b449ea595f9fc764) @@ -243,15 +243,9 @@ private class A {} - private class PropertiesForA : IObjectProperties - { - public object Data { get; set; } - } + private class PropertiesForA : ObjectProperties {} - private class AlternativePropertiesForA : IObjectProperties - { - public object Data { get; set; } - } + private class AlternativePropertiesForA : ObjectProperties {} private class InheritsFromPropertiesForA : PropertiesForA {} @@ -262,11 +256,6 @@ public string Name { get; set; } } - private class PropertiesForB : IObjectProperties - { - public object Data { get; set; } - } - #endregion } } \ No newline at end of file Index: Core/Common/test/Core.Common.Gui.Test/PropertyBag/ObjectPropertiesTest.cs =================================================================== diff -u -r67284323e2785c651633d9c52049ba12a9c70e6a -re217c241d1d57575c99e1062b449ea595f9fc764 --- Core/Common/test/Core.Common.Gui.Test/PropertyBag/ObjectPropertiesTest.cs (.../ObjectPropertiesTest.cs) (revision 67284323e2785c651633d9c52049ba12a9c70e6a) +++ Core/Common/test/Core.Common.Gui.Test/PropertyBag/ObjectPropertiesTest.cs (.../ObjectPropertiesTest.cs) (revision e217c241d1d57575c99e1062b449ea595f9fc764) @@ -22,6 +22,7 @@ using System; using System.ComponentModel; using System.Reflection; +using Core.Common.Base; using Core.Common.Gui.PropertyBag; using NUnit.Framework; @@ -38,6 +39,7 @@ // Assert Assert.IsInstanceOf(properties); + Assert.IsInstanceOf(properties); Assert.IsNull(properties.Data); } @@ -73,5 +75,50 @@ // Assert Assert.AreEqual(BrowsableAttribute.No, browsableAttribute); } + + [Test] + public void GivenObjectPropertiesWithObservableDataSet_WhenNotifyingObserver_RefreshRequiredEventRaised() + { + // Given + var observable = new SimpleObservable(); + using (var properties = new ObjectProperties() + { + Data = observable + }) + { + var refreshRequiredRaised = 0; + properties.RefreshRequired += (sender, args) => refreshRequiredRaised++; + + // When + observable.NotifyObservers(); + + // Then + Assert.AreEqual(1, refreshRequiredRaised); + } + } + + [Test] + public void GivenObjectPropertiesWithObservableDataSet_WhenNotifyingObserverAfterDispose_RefreshRequiredEventNotRaised() + { + // Given + var refreshRequiredRaised = 0; + + var observable = new SimpleObservable(); + using (var properties = new ObjectProperties() + { + Data = observable + }) + { + properties.RefreshRequired += (sender, args) => refreshRequiredRaised++; + } + + // When + observable.NotifyObservers(); + + // Then + Assert.AreEqual(0, refreshRequiredRaised); + } + + private class SimpleObservable : Observable {} } } \ No newline at end of file Index: Core/Plugins/test/Core.Plugins.Map.Test/UITypeEditors/MetaDataAttributeEditorTest.cs =================================================================== diff -u -r1bbf51443c907b5f202e80764fa05f2e7f842c04 -re217c241d1d57575c99e1062b449ea595f9fc764 --- Core/Plugins/test/Core.Plugins.Map.Test/UITypeEditors/MetaDataAttributeEditorTest.cs (.../MetaDataAttributeEditorTest.cs) (revision 1bbf51443c907b5f202e80764fa05f2e7f842c04) +++ Core/Plugins/test/Core.Plugins.Map.Test/UITypeEditors/MetaDataAttributeEditorTest.cs (.../MetaDataAttributeEditorTest.cs) (revision e217c241d1d57575c99e1062b449ea595f9fc764) @@ -103,7 +103,7 @@ return new SelectableMetaDataAttribute(string.Empty); } - private class ObjectPropertiesWithSelectableMetaDataAttribute : IHasMetaData + private class ObjectPropertiesWithSelectableMetaDataAttribute : ObjectProperties, IHasMetaData { private readonly IEnumerable selectableMetaDataAttributes; @@ -114,8 +114,6 @@ this.selectableMetaDataAttributes = selectableMetaDataAttributes; } - public object Data { get; set; } - public SelectableMetaDataAttribute SelectedMetaDataAttribute { get; } public IEnumerable GetAvailableMetaDataAttributes() Index: Ringtoets/Common/test/Ringtoets.Common.Forms.Test/UITypeEditors/ForeshoreProfileEditorTest.cs =================================================================== diff -u -r1bbf51443c907b5f202e80764fa05f2e7f842c04 -re217c241d1d57575c99e1062b449ea595f9fc764 --- Ringtoets/Common/test/Ringtoets.Common.Forms.Test/UITypeEditors/ForeshoreProfileEditorTest.cs (.../ForeshoreProfileEditorTest.cs) (revision 1bbf51443c907b5f202e80764fa05f2e7f842c04) +++ Ringtoets/Common/test/Ringtoets.Common.Forms.Test/UITypeEditors/ForeshoreProfileEditorTest.cs (.../ForeshoreProfileEditorTest.cs) (revision e217c241d1d57575c99e1062b449ea595f9fc764) @@ -127,7 +127,7 @@ } } - private class ObjectPropertiesWithForeshoreProfile : IHasForeshoreProfileProperty + private class ObjectPropertiesWithForeshoreProfile : ObjectProperties, IHasForeshoreProfileProperty { private readonly IEnumerable availableForeshoreProfiles; @@ -137,8 +137,6 @@ this.availableForeshoreProfiles = availableForeshoreProfiles; } - public object Data { get; set; } - public ForeshoreProfile ForeshoreProfile { get; } public IEnumerable GetAvailableForeshoreProfiles() Index: Ringtoets/Common/test/Ringtoets.Common.Forms.Test/UITypeEditors/HydraulicBoundaryLocationEditorTest.cs =================================================================== diff -u -r908d145dae76d17a6e4a2274a2ffbc1aa72871cf -re217c241d1d57575c99e1062b449ea595f9fc764 --- Ringtoets/Common/test/Ringtoets.Common.Forms.Test/UITypeEditors/HydraulicBoundaryLocationEditorTest.cs (.../HydraulicBoundaryLocationEditorTest.cs) (revision 908d145dae76d17a6e4a2274a2ffbc1aa72871cf) +++ Ringtoets/Common/test/Ringtoets.Common.Forms.Test/UITypeEditors/HydraulicBoundaryLocationEditorTest.cs (.../HydraulicBoundaryLocationEditorTest.cs) (revision e217c241d1d57575c99e1062b449ea595f9fc764) @@ -115,7 +115,7 @@ return new SelectableHydraulicBoundaryLocation(new HydraulicBoundaryLocation(1, "", 0, 0), null); } - private class ObjectPropertiesWithSelectableHydraulicBoundaryLocation : IHasHydraulicBoundaryLocationProperty + private class ObjectPropertiesWithSelectableHydraulicBoundaryLocation : ObjectProperties, IHasHydraulicBoundaryLocationProperty { private readonly IEnumerable selectableHydraulicBoundaryLocations; @@ -126,8 +126,6 @@ this.selectableHydraulicBoundaryLocations = selectableHydraulicBoundaryLocations; } - public object Data { get; set; } - public SelectableHydraulicBoundaryLocation SelectedHydraulicBoundaryLocation { get; } public IEnumerable GetSelectableHydraulicBoundaryLocations() Index: Ringtoets/Common/test/Ringtoets.Common.Forms.Test/UITypeEditors/StructureEditorTest.cs =================================================================== diff -u -r1bbf51443c907b5f202e80764fa05f2e7f842c04 -re217c241d1d57575c99e1062b449ea595f9fc764 --- Ringtoets/Common/test/Ringtoets.Common.Forms.Test/UITypeEditors/StructureEditorTest.cs (.../StructureEditorTest.cs) (revision 1bbf51443c907b5f202e80764fa05f2e7f842c04) +++ Ringtoets/Common/test/Ringtoets.Common.Forms.Test/UITypeEditors/StructureEditorTest.cs (.../StructureEditorTest.cs) (revision e217c241d1d57575c99e1062b449ea595f9fc764) @@ -104,7 +104,7 @@ mockRepository.VerifyAll(); } - private class ObjectPropertiesWithStructure : IHasStructureProperty + private class ObjectPropertiesWithStructure : ObjectProperties, IHasStructureProperty { private readonly IEnumerable availableStructures; @@ -114,8 +114,6 @@ this.availableStructures = availableStructures; } - public object Data { get; set; } - public TestStructure Structure { get; } public IEnumerable GetAvailableStructures()