I'm playing with the ArcGIS runtime SDK for .NET. I want to be able to generate multiple polylines in code, the be able to later select them in the map with a mouse click and change the colors. Any idea how to accomplish this?
Solved! Go to Solution.
Hi Michael -
One way to accomplish this would be to display the lines as graphics. Unlike other types of layers, a GraphicsOverlay (or GraphicsLayer) will allow you to assign individual symbols to each graphic (as opposed to assigning a renderer for the entire layer, ie). You could perform a hit test on the graphics (on MapViewTapped, eg.) and update the symbol (color) for the line that the user selects.
Here's an example (including a button handler for creating the lines):
XAML:
<Grid>
<esri:MapView x:Name="MyMapView"
LayerLoaded="MyMapView_LayerLoaded">
<esri:MapView.GraphicsOverlays>
<esri:GraphicsOverlay ID="MyLineGraphics">
<esri:GraphicsOverlay.Renderer>
<esri:SimpleRenderer>
<esri:SimpleLineSymbol Color="DarkGray" Width="2" Style="Dash"/>
</esri:SimpleRenderer>
</esri:GraphicsOverlay.Renderer>
</esri:GraphicsOverlay>
</esri:MapView.GraphicsOverlays>
<esri:Map>
<esri:ArcGISTiledMapServiceLayer ID="Basemap"
ServiceUri="http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer"/>
</esri:Map>
</esri:MapView>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Top">
<Button x:Name="AddLineButton"
Content="Add Line ..."
Click="AddLineButton_Click"/>
<RadioButton Content="Red" IsChecked="True" Checked="RadioButton_Checked"/>
<RadioButton Content="Blue" Checked="RadioButton_Checked"/>
<RadioButton Content="Green" Checked="RadioButton_Checked"/>
</StackPanel>
</Grid>
Code behind (C#):
public partial class MainWindow : Window
{
private SimpleLineSymbol _lineSymbol;
public MainWindow()
{
InitializeComponent();
MyMapView.MapViewTapped += MyMapView_MapViewTapped;
}
// Do a hit test when the map view is tapped
// change the color of the selected graphic (polyline)
async void MyMapView_MapViewTapped(object sender, MapViewInputEventArgs e)
{
var graphicsOverlay = MyMapView.GraphicsOverlays["MyLineGraphics"];
var graphic = await graphicsOverlay.HitTestAsync(MyMapView, e.Position);
if (graphic != null)
{
// Line symbol color is controlled by a radio button choice
graphic.Symbol = _lineSymbol;
}
}
// Button click handler to add lines (with the default gray symbol)
private async void AddLineButton_Click(object sender, RoutedEventArgs e)
{
var newLine = await MyMapView.Editor.RequestShapeAsync(DrawShape.Polyline);
var newGraphic = new Graphic(newLine);
var graphicsOverlay = MyMapView.GraphicsOverlays["MyLineGraphics"];
graphicsOverlay.Graphics.Add(newGraphic);
}
// Radio button handler to determine the line color when a line is clicked
private void RadioButton_Checked(object sender, RoutedEventArgs e)
{
_lineSymbol = new SimpleLineSymbol
{
Style = SimpleLineStyle.Solid,
Width = 2
};
var rb = sender as RadioButton;
switch (rb.Content.ToString())
{
case "Red":
_lineSymbol.Color = Colors.Red;
break;
case "Green":
_lineSymbol.Color = Colors.Green;
break;
case "Blue":
_lineSymbol.Color = Colors.Blue;
break;
default:
break;
}
}
}
Hi Michael -
One way to accomplish this would be to display the lines as graphics. Unlike other types of layers, a GraphicsOverlay (or GraphicsLayer) will allow you to assign individual symbols to each graphic (as opposed to assigning a renderer for the entire layer, ie). You could perform a hit test on the graphics (on MapViewTapped, eg.) and update the symbol (color) for the line that the user selects.
Here's an example (including a button handler for creating the lines):
XAML:
<Grid>
<esri:MapView x:Name="MyMapView"
LayerLoaded="MyMapView_LayerLoaded">
<esri:MapView.GraphicsOverlays>
<esri:GraphicsOverlay ID="MyLineGraphics">
<esri:GraphicsOverlay.Renderer>
<esri:SimpleRenderer>
<esri:SimpleLineSymbol Color="DarkGray" Width="2" Style="Dash"/>
</esri:SimpleRenderer>
</esri:GraphicsOverlay.Renderer>
</esri:GraphicsOverlay>
</esri:MapView.GraphicsOverlays>
<esri:Map>
<esri:ArcGISTiledMapServiceLayer ID="Basemap"
ServiceUri="http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer"/>
</esri:Map>
</esri:MapView>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Top">
<Button x:Name="AddLineButton"
Content="Add Line ..."
Click="AddLineButton_Click"/>
<RadioButton Content="Red" IsChecked="True" Checked="RadioButton_Checked"/>
<RadioButton Content="Blue" Checked="RadioButton_Checked"/>
<RadioButton Content="Green" Checked="RadioButton_Checked"/>
</StackPanel>
</Grid>
Code behind (C#):
public partial class MainWindow : Window
{
private SimpleLineSymbol _lineSymbol;
public MainWindow()
{
InitializeComponent();
MyMapView.MapViewTapped += MyMapView_MapViewTapped;
}
// Do a hit test when the map view is tapped
// change the color of the selected graphic (polyline)
async void MyMapView_MapViewTapped(object sender, MapViewInputEventArgs e)
{
var graphicsOverlay = MyMapView.GraphicsOverlays["MyLineGraphics"];
var graphic = await graphicsOverlay.HitTestAsync(MyMapView, e.Position);
if (graphic != null)
{
// Line symbol color is controlled by a radio button choice
graphic.Symbol = _lineSymbol;
}
}
// Button click handler to add lines (with the default gray symbol)
private async void AddLineButton_Click(object sender, RoutedEventArgs e)
{
var newLine = await MyMapView.Editor.RequestShapeAsync(DrawShape.Polyline);
var newGraphic = new Graphic(newLine);
var graphicsOverlay = MyMapView.GraphicsOverlays["MyLineGraphics"];
graphicsOverlay.Graphics.Add(newGraphic);
}
// Radio button handler to determine the line color when a line is clicked
private void RadioButton_Checked(object sender, RoutedEventArgs e)
{
_lineSymbol = new SimpleLineSymbol
{
Style = SimpleLineStyle.Solid,
Width = 2
};
var rb = sender as RadioButton;
switch (rb.Content.ToString())
{
case "Red":
_lineSymbol.Color = Colors.Red;
break;
case "Green":
_lineSymbol.Color = Colors.Green;
break;
case "Blue":
_lineSymbol.Color = Colors.Blue;
break;
default:
break;
}
}
}
Thank you very much for the detailed example! Greatly appreciated.