Thanks for the reply Brian. Here's another example. I have a collection of business objects I want to put on a GraphicsLayer. Properties of those objects should determine the image of the Graphic and the text shown. In WPF I had a MarkerSymbol ControlTemplate for a GraphicsLayer that bound to the attributes of the graphic.
<esri:MarkerSymbol x:Key="unitPlotSymbol">
<esri:MarkerSymbol.ControlTemplate>
<ControlTemplate>
<Border BorderBrush="DarkGray" BorderThickness="1">
<Grid Margin="0,0,0,0" HorizontalAlignment="Center" VerticalAlignment="Bottom">
<Image x:Name="unitPlotImage" Source="{Binding Attributes[IMAGE]}" Stretch="None"></Image>
<TextBlock FontSize="14" Foreground="Black" FontWeight="Bold" Text="{Binding Attributes[LABEL]}" HorizontalAlignment="Center" />
</Grid>
</Border>
</ControlTemplate>
</esri:MarkerSymbol.ControlTemplate>
</esri:MarkerSymbol>
It's nice, I just created the Graphics with the proper Attributes and added them to the layer. The correct image and label were applied. I don't see how this is doable in Runtime for .NET. since TextSymbols cannot bind. Now, I need to build each graphic programmatically in the ViewModel like so:
foreach (CADws.UnitInfo u in units)
{
Graphic g = new Graphic();
g.Geometry = new MapPoint(u.WebMercLon, u.WebMercLat, new SpatialReference(Constants.WEB_MERC_SPATIAL_REF));
CompositeSymbol cs = new CompositeSymbol();
PictureMarkerSymbol ps = new PictureMarkerSymbol();
ps.SetSource(System.IO.File.ReadAllBytes(@"C:\GIS\Resources\" + DetermineApproriateSymbol(u)));
TextSymbol ts = new TextSymbol();
ts.Color = Colors.Black;
ts.Text = u.UnitNum;
ts.XOffset = -14;
ts.YOffset = 0;
ts.Font.FontWeight = SymbolFontWeight.Bold;
ts.Font.FontSize = 16;
cs.Symbols.Add(ps);
cs.Symbols.Add(ts);
g.Symbol = cs;
g.Attributes["LABEL"] = u.UnitNum;
if (u.Type != "P") {
g.Attributes["DETAILS1"] = String.Format("{0} {1}", u.UnitNum, GetNiceStatus(u.Status));
g.Attributes["DETAILS2"] = u.CallInfo;
g.Attributes["DETAILS3"] = u.KnownLocation;
g.Attributes["DETAILS4"] = "";
}
else
{
g.Attributes["DETAILS1"] = String.Format("{0} {1} Radio:{2}", u.UnitNum,GetNiceStatus(u.Status),u.TalkGroup);
g.Attributes["DETAILS2"] = u.CallInfo;
g.Attributes["DETAILS3"] = u.KnownLocation;
g.Attributes["DETAILS4"] = u.OfficerInfo;
}
graphics.Add(g);
}
Then add that collection to my GraphicsLayer.
(Initially I thought I'd just expose a ObservableCollection of Graphics from the ViewModel that the GraphicsLayer could bind to, but the elements in the MapView don't inherit it's DataContext and setting it for every element in the map programmatically seemed like a poor design.)
So clearly I'm violating MVVM above. The ViewModel here is dictating how the View looks. How else can this be done?