private GraphicsLayer addedLayer; private GraphicsLayer graphicsLayer; void Layers_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add) { foreach (var item in e.NewItems) if (item is GraphicsLayer) { addedLayer = item as GraphicsLayer; graphicsLayer = this.MyMap.Layers["MeasureGraphicsLayer"] as GraphicsLayer; graphicsLayer.Visible = false; (item as GraphicsLayer).Graphics.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Graphics_CollectionChanged); } } if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove) { if (addedLayer != null) { isDrawOver = true; graphicsLayer.Visible = true; } } } void Graphics_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add) { glCollectionChanged = true; if (isDrawOver == false) { graphicsLayer.ClearGraphics(); } else { isDrawOver = false; } if (graphicsLayer != null) { foreach (Graphic item in addedLayer.Graphics) { Graphic g = item as Graphic; graphicsLayer.Graphics.Add(new Graphic() { Geometry = g.Geometry, Symbol = g.Symbol }); } } } }
Ok,
I did the impossible. I got my application to keep the measure action graphics layer after the draw completes(user double clicks).
What this does is add the existing graphics from the added graphics layer (not from the CollectionChangedEventArgs.NewItems property) to a new graphics layer I put on my map. Then each time the user clicks, that graphics layer is cleared, and the next state of the measure action graphics layer is added to that graphics layer. It is cleared each time until the the double click, where a global bool tracks if the user double clicked. If that bool is satisfied, the graphics layer is not cleared, and you are left with the final state of the measure action graphics layer. Easy, right!?
I had an epiphany over the weekend and the logic worked through my head, and wouldn't you know it, it works great!! I out smarted measure action, and now it is finally worth something to me!
If you want to try my this implementation of measure action, go to http://gis.modestogov.com
My users will be happy!!!!!
Patrick
isDrawOver should always be false except when the measure graphics layer is removed (true), then it is reset to false waiting for the next measure to happen. I simply use that so I can track when the user is done measuring, so then I freeze the graphics layer and then make it visible.
you should not need glCollectionChanged, I used this to meet the need of my specific application, you should just delete that out.
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add) { foreach (var item in e.NewItems) if (item is GraphicsLayer) { addedLayer = item as GraphicsLayer; graphicsLayer = this.MyMap.Layers["MeasureGraphicsLayer"] as GraphicsLayer; graphicsLayer.Visible = false; }
If I am understanding your question, that happens here when the measure tool is first activatedif (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add) { foreach (var item in e.NewItems) if (item is GraphicsLayer) { addedLayer = item as GraphicsLayer; graphicsLayer = this.MyMap.Layers["MeasureGraphicsLayer"] as GraphicsLayer; graphicsLayer.Visible = false; }
Then I simply copy the graphics from added layer to graphicslayer. addedlayer is set to the graphic that the measure tool adds to the map, every time the tool is invoked. graphicslayer is a layer that I put on the map and is loaded when the map initializes.
I am not sure I answered your question.
<!-- Measure Tools Window--> <userControls:WindowPanel x:Name="MeasureTools" HorizontalAlignment="Left" Margin="420,10,0,0" VerticalAlignment="Top" IsOpen="{Binding ElementName=ToolsMenu_Measure, Path=IsChecked, Mode=TwoWay}"> <StackPanel Orientation="Vertical" Margin="5"> <StackPanel Orientation="Horizontal" Margin="5"> <RadioButton Content="Distance" ToolTipService.ToolTip="Distance" GroupName="MeasureMode" Margin="5,0,0,0" Foreground="White" FontSize="11" Click="MeasureTools_Click"> <!--<i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <esri:MeasureAction AreaUnit="SquareMiles" DisplayTotals="True" DistanceUnit="Miles" MapUnits="Feet" MeasureMode="Polyline" FillSymbol="{StaticResource DefaultFillSymbol}" TargetName="MyMap"/> </i:EventTrigger> </i:Interaction.Triggers>--> </RadioButton> <RadioButton Content="Area" ToolTipService.ToolTip="Area" GroupName="MeasureMode" Margin="5,0,0,0" Foreground="White" FontSize="11" Click="MeasureTools_Click"> <!--<i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <esri:MeasureAction AreaUnit="SquareMiles" DisplayTotals="True" DistanceUnit="Miles" MapUnits="Feet" MeasureMode="Polygon" FillSymbol="{StaticResource DefaultFillSymbol}" TargetName="MyMap" /> </i:EventTrigger> </i:Interaction.Triggers>--> </RadioButton> <RadioButton Content="Clear" ToolTipService.ToolTip="Clear" IsChecked="True" GroupName="MeasureMode" Margin="5,0,0,0" Foreground="White" FontSize="11" Click="MeasureTools_Click"> </RadioButton> </StackPanel> <TextBlock Foreground="Yellow" FontSize="11" Text="Double-Click to Complete" TextWrapping="NoWrap" Height="Auto" HorizontalAlignment="Center" Margin="5,3,0,0" FontStyle="Italic" /> </StackPanel> <userControls:WindowPanel.ContentTitle> <StackPanel Orientation="Horizontal"> <Image Source="Images/icons/i_measure.png" HorizontalAlignment="Left" VerticalAlignment="Top" Stretch="Fill" Width="20" Height="20" Margin="5,2,0,0" /> <TextBlock Foreground="White" FontSize="12" Text="Measure" Width="100" TextWrapping="NoWrap" Height="Auto" HorizontalAlignment="Left" Margin="5,3,0,0" /> </StackPanel> </userControls:WindowPanel.ContentTitle> </userControls:WindowPanel>
#region MeasureTool private GraphicsLayer addedLayer; private GraphicsLayer MeasureGraphicsLayer; private myMeasureAction ma = new myMeasureAction(); private string MeasureTool = null; private class myMeasureAction : ESRI.ArcGIS.Client.Actions.MeasureAction { public void Execute() { Invoke(null); } } private void MeasureTools_Click(object sender, System.Windows.RoutedEventArgs e) { if ((RadioButton)sender != null) { MeasureTool = ((RadioButton)sender).Content.ToString(); MeasureGraphicsLayer = this.MyMap.Layers["MeasureGraphicsLayer"] as GraphicsLayer; MeasureGraphicsLayer.ClearGraphics(); MeasureGraphicsLayer.Visible = false; ma.DisplayTotals = true; ma.AreaUnit = ESRI.ArcGIS.Client.Actions.AreaUnit.SquareMiles; ma.DistanceUnit = ESRI.ArcGIS.Client.Actions.DistanceUnit.Miles; ma.FillSymbol = LayoutRoot.Resources["DefaultFillSymbol"] as FillSymbol; ma.Attach(MyMap); //MeasureTool = ((RadioButton)sender).Content.ToString(); if (MeasureTool == "Distance") { ma.MeasureMode = myMeasureAction.Mode.Polyline; ma.Execute(); } else if (MeasureTool == "Area") { ma.MeasureMode = myMeasureAction.Mode.Polygon; ma.Execute(); } else { MeasureGraphicsLayer.ClearGraphics(); MeasureGraphicsLayer.Visible = false; ma.Detach(); } } } private void MeasureTools_Clear_Click(object sender, RoutedEventArgs e) { MeasureGraphicsLayer.ClearGraphics(); MeasureGraphicsLayer.Visible = false; ma.Detach(); } private void Layers_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add) { foreach (var item in e.NewItems) { if (item is GraphicsLayer) { addedLayer = item as GraphicsLayer; MeasureGraphicsLayer = this.MyMap.Layers["MeasureGraphicsLayer"] as GraphicsLayer; MeasureGraphicsLayer.Visible = false; (item as GraphicsLayer).Graphics.CollectionChanged += Graphics_CollectionChanged; } } } if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove) { if (addedLayer != null) { isDrawOver = true; MeasureGraphicsLayer.Visible = true; //Tried to rerun here....but error } } } private void Graphics_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add) { if (isDrawOver == false) { MeasureGraphicsLayer.ClearGraphics(); } else { isDrawOver = false; } if (MeasureGraphicsLayer != null) { foreach (Graphic item in addedLayer.Graphics) { Graphic g = item as Graphic; MeasureGraphicsLayer.Graphics.Add(new Graphic() { Geometry = g.Geometry, Symbol = g.Symbol }); } } } else { //MessageBox.Show(e.Action.ToString()); } } #endregion
Ok,
I did the impossible. I got my application to keep the measure action graphics layer after the draw completes(user double clicks).
What this does is add the existing graphics from the added graphics layer (not from the CollectionChangedEventArgs.NewItems property) to a new graphics layer I put on my map. Then each time the user clicks, that graphics layer is cleared, and the next state of the measure action graphics layer is added to that graphics layer. It is cleared each time until the the double click, where a global bool tracks if the user double clicked. If that bool is satisfied, the graphics layer is not cleared, and you are left with the final state of the measure action graphics layer. Easy, right!?
I had an epiphany over the weekend and the logic worked through my head, and wouldn't you know it, it works great!! I out smarted measure action, and now it is finally worth something to me!
If you want to try my this implementation of measure action, go to http://gis.modestogov.com
My users will be happy!!!!!
Patrickprivate GraphicsLayer addedLayer; private GraphicsLayer graphicsLayer; void Layers_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add) { foreach (var item in e.NewItems) if (item is GraphicsLayer) { addedLayer = item as GraphicsLayer; graphicsLayer = this.MyMap.Layers["MeasureGraphicsLayer"] as GraphicsLayer; graphicsLayer.Visible = false; (item as GraphicsLayer).Graphics.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Graphics_CollectionChanged); } } if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove) { if (addedLayer != null) { isDrawOver = true; graphicsLayer.Visible = true; } } } void Graphics_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add) { glCollectionChanged = true; if (isDrawOver == false) { graphicsLayer.ClearGraphics(); } else { isDrawOver = false; } if (graphicsLayer != null) { foreach (Graphic item in addedLayer.Graphics) { Graphic g = item as Graphic; graphicsLayer.Graphics.Add(new Graphic() { Geometry = g.Geometry, Symbol = g.Symbol }); } } } }