Index: Core/GIS/src/Core.GIS.SharpMap.Api/IMap.cs =================================================================== diff -u -ree0b95b2a1a34d8e81a21c8d05ef1354169af50c -rc9f937248bfbebc0373784594fb0e7bb5e2912bd --- Core/GIS/src/Core.GIS.SharpMap.Api/IMap.cs (.../IMap.cs) (revision ee0b95b2a1a34d8e81a21c8d05ef1354169af50c) +++ Core/GIS/src/Core.GIS.SharpMap.Api/IMap.cs (.../IMap.cs) (revision c9f937248bfbebc0373784594fb0e7bb5e2912bd) @@ -60,7 +60,7 @@ /// /// A collection of layers. The first layer in the list is drawn first, the last one on top. /// - IEventedList Layers { get; set; } + EventedList Layers { get; set; } /// /// Map background color (defaults to transparent) @@ -134,14 +134,6 @@ bool IsDisposing { get; } - /// - /// Replacing layer is used, because we cannot use Layers[i] = layer. - /// This is because there are a lot of places that have a NotImplementedException when - /// a replace event in the collection occurs. - /// HACK - /// - bool ReplacingLayer { get; } - void ClearImage(); /// Index: Core/GIS/src/Core.GIS.SharpMap/Layers/VectorLayer.cs =================================================================== diff -u -r5869dc3e57dfc3f16d35a28154f7304c66952906 -rc9f937248bfbebc0373784594fb0e7bb5e2912bd --- Core/GIS/src/Core.GIS.SharpMap/Layers/VectorLayer.cs (.../VectorLayer.cs) (revision 5869dc3e57dfc3f16d35a28154f7304c66952906) +++ Core/GIS/src/Core.GIS.SharpMap/Layers/VectorLayer.cs (.../VectorLayer.cs) (revision c9f937248bfbebc0373784594fb0e7bb5e2912bd) @@ -100,7 +100,7 @@ { if (layer.Style != null) { - style = (VectorStyle) layer.Style.Clone(); + Style = (VectorStyle) layer.Style.Clone(); isStyleDirty = true; } @@ -238,7 +238,7 @@ protected virtual void OnInitializeDefaultStyle() { - style = new VectorStyle(); + Style = new VectorStyle(); UpdateStyleGeometry(); } Index: Core/GIS/src/Core.GIS.SharpMap/Map/Map.cs =================================================================== diff -u -r019659033f11f75408fd860bdca238616244491a -rc9f937248bfbebc0373784594fb0e7bb5e2912bd --- Core/GIS/src/Core.GIS.SharpMap/Map/Map.cs (.../Map.cs) (revision 019659033f11f75408fd860bdca238616244491a) +++ Core/GIS/src/Core.GIS.SharpMap/Map/Map.cs (.../Map.cs) (revision c9f937248bfbebc0373784594fb0e7bb5e2912bd) @@ -17,15 +17,14 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.Globalization; using System.Linq; using Core.Common.Base; using Core.Common.Utils; -using Core.Common.Utils.Aop; -using Core.Common.Utils.Aop.Markers; using Core.Common.Utils.Collections; using Core.Common.Utils.Collections.Generic; using Core.GIS.GeoAPI.CoordinateSystems; @@ -80,9 +79,7 @@ /// System.Drawing.Image imgMap = myMap.GetMap(); //Renders the map /// /// - [Entity(FireOnCollectionChange = false)] - //[Serializable] - public class Map : Observable, IDisposable, INotifyCollectionChange, IMap + public class Map : Observable, IDisposable, INotifyCollectionChange, INotifyPropertyChange, IMap { /// /// When layer render time is less than this - image will not be cached, increase this parameter when you get memory leaks. @@ -100,7 +97,7 @@ private const int defaultExtendsMarginPercentage = 10; private static readonly ILog log = LogManager.GetLogger(typeof(Map)); - private IEventedList layers; + private EventedList layers; private double worldHeight; private double worldLeft; @@ -148,7 +145,6 @@ /// /// Calling Render() resets this flag automatically. /// - [NoNotifyPropertyChange] public virtual bool RenderRequired { get; protected set; } public virtual Image Image @@ -174,6 +170,8 @@ } set { + OnPropertyChanging("ShowGrid"); + showGrid = value; if (value) @@ -186,11 +184,11 @@ } RenderRequired = true; + + OnPropertyChanged("ShowGrid"); } } - public bool ReplacingLayer { get; private set; } - /// /// Returns the (first) layer on which is present. /// @@ -749,7 +747,6 @@ public void ReplaceLayer(ILayer sourceLayer, ILayer targetLayer) { - ReplacingLayer = true; sourceLayer.ThemeGroup = sourceLayer.Name; sourceLayer.ShowInTreeView = false; targetLayer.ThemeGroup = sourceLayer.ThemeGroup; @@ -785,7 +782,6 @@ } } - ReplacingLayer = false; NotifyObservers(); } @@ -1016,6 +1012,8 @@ } set { + OnPropertyChanging("MapTransform"); + mapTransform = value; if (mapTransform.IsInvertible) { @@ -1028,6 +1026,8 @@ } SetRenderRequiredForAllLayers(); + + OnPropertyChanged("MapTransform"); } } @@ -1046,9 +1046,12 @@ } set { - srsWkt = value; + OnPropertyChanging("SrsWkt"); + srsWkt = value; CreateCoordinateSystemFromWkt(value); + + OnPropertyChanged("SrsWkt"); } } @@ -1088,6 +1091,8 @@ } set { + OnPropertyChanging("CoordinateSystem"); + srsWkt = null; if (value != null) @@ -1124,6 +1129,8 @@ } } ZoomToExtents(); + + OnPropertyChanged("CoordinateSystem"); } } @@ -1181,12 +1188,16 @@ } set { + OnPropertyChanging("SRID"); + srid = value; if (CoordinateSystemFactory != null) { CoordinateSystem = CoordinateSystemFactory.CreateFromEPSG(srid); } + + OnPropertyChanged("SRID"); } } @@ -1195,7 +1206,7 @@ /// /// A collection of layers. The first layer in the list is drawn first, the last one on top. /// - public virtual IEventedList Layers + public virtual EventedList Layers { get { @@ -1215,6 +1226,8 @@ { if (layers != null) { + layers.PropertyChanging -= OnPropertyChanging; + layers.PropertyChanged -= OnPropertyChanged; layers.CollectionChanging -= LayersCollectionChanging; layers.CollectionChanged -= LayersCollectionChanged; } @@ -1223,6 +1236,8 @@ if (layers != null) { + layers.PropertyChanging += OnPropertyChanging; + layers.PropertyChanged += OnPropertyChanged; layers.CollectionChanging += LayersCollectionChanging; layers.CollectionChanged += LayersCollectionChanged; } @@ -1380,11 +1395,15 @@ } set { + OnPropertyChanging("BackColor"); + backColor = value; if (MapViewOnChange != null) { MapViewOnChange(); } + + OnPropertyChanged("BackColor"); } } @@ -1401,11 +1420,15 @@ } set { + OnPropertyChanging("Center"); + center = value; desiredEnvelope.SetCentre(center); ZoomToFit(desiredEnvelope, false); + + OnPropertyChanged("Center"); } } @@ -1431,6 +1454,8 @@ } set { + OnPropertyChanging("Zoom"); + double oldZoom = zoom; double clippedZoom; @@ -1452,6 +1477,8 @@ ZoomToFit(desiredEnvelope, false); zoom = clippedZoom; //using intermediate value because desired.Zoom(100*) causes minor rounding issues in ZoomToFit + + OnPropertyChanged("Zoom"); } } @@ -1583,9 +1610,14 @@ { throw new ArgumentException("Invalid Pixel Aspect Ratio"); } + + OnPropertyChanging("PixelAspectRatio"); + pixelAspectRatio = value; UpdateDimensions(); SetRenderRequiredForAllLayers(); + + OnPropertyChanged("PixelAspectRatio"); } } @@ -1614,8 +1646,12 @@ } set { + OnPropertyChanging("Size"); + size = value; ZoomToFit(desiredEnvelope ?? Envelope, false); + + OnPropertyChanged("Size"); } } @@ -1636,8 +1672,13 @@ { throw (new ArgumentException("Minimum zoom must be 0 or more")); } + + OnPropertyChanging("MinimumZoom"); + minimumZoom = value; SetRenderRequiredForAllLayers(); + + OnPropertyChanged("MinimumZoom"); } } @@ -1664,8 +1705,13 @@ { throw (new ArgumentException("Maximum zoom must larger than 0")); } + + OnPropertyChanging("MaximumZoom"); + maximumZoom = value; SetRenderRequiredForAllLayers(); + + OnPropertyChanged("MaximumZoom"); } } @@ -1677,7 +1723,9 @@ } set { + OnPropertyChanging("Name"); name = value; + OnPropertyChanged("Name"); } } @@ -1699,5 +1747,45 @@ } #endregion + + #region INotifyPropertyChange + + public event PropertyChangingEventHandler PropertyChanging; + + protected void OnPropertyChanging(string propertyName) + { + if (PropertyChanging != null) + { + PropertyChanging(this, new PropertyChangingEventArgs(propertyName)); + } + } + + protected void OnPropertyChanging(object sender, PropertyChangingEventArgs e) + { + if (PropertyChanging != null) + { + PropertyChanging(sender, e); + } + } + + public event PropertyChangedEventHandler PropertyChanged; + + protected void OnPropertyChanged(string propertyName) + { + if (PropertyChanged != null) + { + PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } + + protected void OnPropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (PropertyChanged != null) + { + PropertyChanged(sender, e); + } + } + + #endregion } } \ No newline at end of file Index: Core/GIS/test/Core.GIS.SharpMap.Tests/MapTest.cs =================================================================== diff -u -r5869dc3e57dfc3f16d35a28154f7304c66952906 -rc9f937248bfbebc0373784594fb0e7bb5e2912bd --- Core/GIS/test/Core.GIS.SharpMap.Tests/MapTest.cs (.../MapTest.cs) (revision 5869dc3e57dfc3f16d35a28154f7304c66952906) +++ Core/GIS/test/Core.GIS.SharpMap.Tests/MapTest.cs (.../MapTest.cs) (revision c9f937248bfbebc0373784594fb0e7bb5e2912bd) @@ -27,16 +27,15 @@ { //TODO: rename this test [Test] - [Ignore("WTI-81 | Will be activated (and will run correctly) when Entity is removed from Map")] public void EventBubbling2() { int changeCount = 0; var map = new Map.Map(new Size(2, 1)); - var vectorLayer = new VectorLayer("EventBubbling"); + var vectorLayer = new VectorLayer("EventBubbling") { Style = new VectorStyle() }; map.Layers.Add(vectorLayer); ((INotifyPropertyChanged) map).PropertyChanged += - delegate(object sender, PropertyChangedEventArgs e) + (sender, e) => { Assert.AreEqual(e.PropertyName, "Line"); changeCount++;