Is it possible to display a user control on the map coordinates, on a map? Say, for instance, I wanted to put a UserControl button on capitals of states in the US and if you clicked on the button, a page would load? Something to place a UserControl onto these coordinates...
Thanks!
Hi terinfire,
you can use SymbolElement to place it at specific coordinates and attach to XamMap's ElementClick.
Another approach would be to use MapLayer's ValueTemplate and set its DataTemplate to Button. You will also need to create an attached property for page address since MapElement doesn't provide one.
In XAML:
<igMap:XamMap x:Name="xamMap1" ElementClick="xamMap1_ElementClick"> <igMap:XamMap.Layers> <igMap:MapLayer x:Name="MapLayer" IsAutoWorldRect="True" > <igMap:MapLayer.Reader> <igMap:ShapeFileReader Uri="Shapefiles/usa/usa_st" DataMapping="Name,Caption=STATE_NAME"/> </igMap:MapLayer.Reader> </igMap:MapLayer>
<igMap:MapLayer x:Name="symbolLayer"> <igMap:MapLayer.ValueTemplate> <DataTemplate> <Button Content="Click me" Click="Button_Click" /> </DataTemplate> </igMap:MapLayer.ValueTemplate> </igMap:MapLayer>
</igMap:XamMap.Layers></igMap:XamMap>
In code behind:
1. Create an attached dependency property to hold page's uri
#region PageAddress
public Uri PageAddress{ get { return (Uri)GetValue(PageAddressProperty); } set { SetValue(PageAddressProperty, value); }}
public static readonly DependencyProperty PageAddressProperty = DependencyProperty.RegisterAttached("PageAddress", typeof(Uri), typeof(ButtonSymbol), new PropertyMetadata(null));
#endregion
2. Add the button that will open a new page on click. The button is added at specific coordinates. Also set the page address.
var element = xamMap1.Layers[0].Elements.FindElement("Name", "Montana").ElementAt(0);
var origin = new Point(element.WorldRect.X + 0.5 * element.WorldRect.Width, element.WorldRect.Y + 0.5 * element.WorldRect.Height);var symbolElement = new SymbolElement { SymbolOrigin = origin, SymbolType = MapSymbolType.None, SymbolSize = 10 };
symbolElement.SetValue(PageAddressProperty, new Uri("http://es.infragistics.com/"));
xamMap1.Layers[1].Elements.Add(symbolElement);
Rect worldRect = xamMap1.Layers[1].WorldRect;worldRect.Union(symbolElement.WorldRect);xamMap1.Layers[1].WorldRect = worldRect;
3. Handle the button click event
private void Button_Click(object sender, RoutedEventArgs e){ var button = (Button) sender; var element = (SymbolElement) (button.DataContext); var uri = (Uri)(element).GetValue(PageAddressProperty);
HtmlPage.Window.Navigate(uri); }
Regards,
Ivan Kotev
This is nice, but is there any way to actually host a UserControl itself? I was only trying to give an example of what I *might* need. Rather, I need to know if there's a way to directly inject/project user controls at specific points. There's a lot of visualization-type elements that I'll need at certain locations on a map (could be buttons, images, meters, etc).
Great idea, Graham. I'll see if that works. Thanks!
Graham,
I've tried to follow this up and do what you posted in the other topic, but am not having any success...
I've made three DependencyProperty's in a custom class that derives from a DependencyObject.
i.e.
public class MapData : DependencyObject { public static readonly DependencyProperty IDProperty = DependencyProperty.RegisterAttached("ID", typeof(object), typeof(MapData), new PropertyMetadata(null)); public static readonly DependencyProperty StatusProperty = DependencyProperty.RegisterAttached("Status", typeof(object), typeof(MapData), new PropertyMetadata(null)); public static readonly DependencyProperty TextProperty = DependencyProperty.RegisterAttached("Text", typeof(object), typeof(MapData), new PropertyMetadata(null)); public static object GetID(DependencyObject target) { return target.GetValue(MapData.IDProperty); } public static void SetID(DependencyObject target, object value) { target.SetValue(MapData.IDProperty, value); } public static object GetStatus(DependencyObject target) { return target.GetValue(MapData.StatusProperty); } public static void SetStatus(DependencyObject target, object value) { target.SetValue(MapData.StatusProperty, value); } public static object GetText(DependencyObject target) { return target.GetValue(MapData.TextProperty); } public static void SetText(DependencyObject target, object value) { target.SetValue(MapData.TextProperty, value); } }
and when objects are added, I call MapData.SetText( element, "Some Text" );
In the XAML, I've mapped the Text of my target control in the DataTemplate to have the Binding Path=(ui:MapData.Text) -- is this correct ? (ui is the namespace of all of my custom controls, which also includes the MapData class)
*bump*
Any help?
Do you get any binding errors in the output log?
Also, some silverlight versions have a bug with binding to attached properties. Do you see in the linked example how I redefined the namespace that contains the attached property class in the element that is binding against the attached property? This is due to a bug in the Silverlight runtime. You may need to make the same adjustment. If that doesn't help, could you share your xaml and I'll take a look at it?
Hope this helps!
-Graham
We ended up having to take an alternative approach due to a lack of support, so this is no longer on the table.