elementMouseLeftButton Issues with DataContext

3 posts, 0 answers
  1. Tim
    Tim avatar
    41 posts
    Member since:
    Oct 2012

    Posted 26 Feb 2014 Link to this post

    I'm trying to set up my polygons to have a click event on them similar to the demo at http://demos.telerik.com/silverlight/#Map/SalesDashboard

    I can get the click event to work, however my element.DataContext is always null.

    Here is what I have:
    xaml

    <UserControl x:Class="ClosestCenter.MainPage"
            xmlns:local="clr-namespace:ClosestCenter"
            mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
         
        <UserControl.Resources>
            <local:WktDataViewModel x:Key="DataContext" />
        </UserControl.Resources>
        <Grid x:Name="LayoutRoot">
            <telerik:RadMap x:Name="radMap" Center="39.36830, -95.27340" ZoomLevel="5" MouseClickMode="None" MapMouseClick="radMap_MouseClick"  >
                <telerik:InformationLayer x:Name="informationLayer" MouseLeftButtonDown="elementMouseLeftButtonDown">
                    <telerik:InformationLayer.Reader>
                        <telerik:SqlGeospatialDataReader Source="{Binding Source={StaticResource DataContext}, Path=WktDataCollection}"
                                                         GeospatialPropertyName="Geometry"
                                                         ToolTipFormat="Name">
                            <telerik:SqlGeospatialDataReader.PointTemplate>
                                <DataTemplate>
                                    <Border Background="Yellow" BorderThickness="1" Padding="2,2,2,2">
                                        <telerik:MapLayer.HotSpot>
                                            <telerik:HotSpot X="0.5" Y="0.5" ElementName="PART_Image" />
                                        </telerik:MapLayer.HotSpot>
                                        <Grid Name="PART_Panel">
                                            <Path Fill="{Binding Source={StaticResource DataContext},Path=PointBrush}" Name="PART_Image">
                                                <Path.Data>
                                                    <GeometryGroup>
                                                        <EllipseGeometry Center="7,7" RadiusX="4" RadiusY="4" />
                                                        <EllipseGeometry Center="7,7" RadiusX="6" RadiusY="6" />
                                                    </GeometryGroup>
                                                </Path.Data>
                                            </Path>
                                        </Grid>
                                    </Border>
                                </DataTemplate>
                            </telerik:SqlGeospatialDataReader.PointTemplate>
                        </telerik:SqlGeospatialDataReader>
                    </telerik:InformationLayer.Reader>
                    <telerik:InformationLayer.ShapeFill>
                        <telerik:MapShapeFill Fill="#7FFFFFFF" Stroke="#5A636B" StrokeThickness="3" />
                    </telerik:InformationLayer.ShapeFill>
                    <telerik:InformationLayer.HighlightFill>
                        <telerik:MapShapeFill Fill="#B2FFFFFF" Stroke="#5A636B" StrokeThickness="3" />
                    </telerik:InformationLayer.HighlightFill>
     
                </telerik:InformationLayer>
            </telerik:RadMap>
        </Grid>
    </UserControl>

    My xaml.cs:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using Telerik.Windows.Controls.Map;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
     
    namespace ClosestCenter
    {
        public partial class MainPage : UserControl
        {
            private WktDataRow lastHighlightedWkt;
            private FrameworkElement clickedElement;
            private WktDataViewModel context;
            //private WktDataViewModel context;
            /*
            private Collection<WktDataRow> _wktDataCollection;
     
            public Collection<WktDataRow> WktDataCollection
            {
                get
                {
                    return this._wktDataCollection;
                }
                set
                {
                    this._wktDataCollection = value;
                }
            }
            */
            public MainPage()
            {
                InitializeComponent();           
     
                this.radMap.Provider = new BingMapProvider(MapMode.Aerial, true, "myKey");
     
                context = this.DataContext as WktDataViewModel;
            }
     
            private void Map_Loaded(object sender, RoutedEventArgs e)
            {          
     
            }
     
           private object GetSenderDataPoint()
            {
                if (this.clickedElement != null)
                {
                    FrameworkElement element = this.clickedElement;
                    this.clickedElement = null;
     
                    return element.DataContext;
                }
     
                return null;
            }
     
            private WktDataRow GetDataPointWkt(object senderDataPoint)
            {
                return (WktDataRow)senderDataPoint;
            }
     
            private void radMap_MouseClick(object sender, MapMouseRoutedEventArgs eventArgs)
            {
                object senderDataPoint = GetSenderDataPoint();
                if (senderDataPoint != null)
                {
                    WktDataRow wkt = this.GetDataPointWkt(senderDataPoint);
     
                    this.SelectWkt(wkt);
                }
            }
     
            private void SelectWkt(WktDataRow wktDataRow)
            {
                string test = wktDataRow.Name;
            }
     
            private void elementMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
                FrameworkElement element = sender as FrameworkElement;
                if (element != null)
                {
                    this.clickedElement = element;
                }
            }
        }
    }

    What am I missing that will allow me to get the DataContext for the section of my map that was clicked? The section in question is GetSenderDataPoint. It is hitting the return element.DataContext but that value is always null.

    Thanks,

    Tim
  2. Tim
    Tim avatar
    41 posts
    Member since:
    Oct 2012

    Posted 27 Feb 2014 in reply to Tim Link to this post

    I made some progress and am able to get past the previous issue but now I'm getting the following error in radMap_MouseClick:

    Unable to cast object of type 'ClosestCenter.MainPageViewModel' to type 'ClosestCenter.CenterArea'.

    Here is my updated code:
    xaml
    <UserControl x:Class="ClosestCenter.MainPage"
            xmlns:local="clr-namespace:ClosestCenter"
            mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
         
        <UserControl.DataContext>
            <local:MainPageViewModel />
        </UserControl.DataContext>
        <Grid x:Name="LayoutRoot">
            <telerik:RadMap x:Name="radMap" Center="39.36830, -95.27340" ZoomLevel="5" MouseClickMode="None" MapMouseClick="radMap_MouseClick"  >
                <telerik:InformationLayer x:Name="informationLayer" MouseLeftButtonDown="elementMouseLeftButtonDown">
                    <telerik:InformationLayer.Reader>
                        <telerik:SqlGeospatialDataReader Source="{Binding CenterAreas}"
                                                         GeospatialPropertyName="Geometry"
                                                         ToolTipFormat="Name">
                            <telerik:SqlGeospatialDataReader.PointTemplate>
                                <DataTemplate>
                                    <Border Background="Yellow" BorderThickness="1" Padding="2,2,2,2">
                                        <telerik:MapLayer.HotSpot>
                                            <telerik:HotSpot X="0.5" Y="0.5" ElementName="PART_Image" />
                                        </telerik:MapLayer.HotSpot>
                                        <Grid Name="PART_Panel">
                                            <Path Fill="{Binding PointBrush}" Name="PART_Image">
                                                <Path.Data>
                                                    <GeometryGroup>
                                                        <EllipseGeometry Center="7,7" RadiusX="4" RadiusY="4" />
                                                        <EllipseGeometry Center="7,7" RadiusX="6" RadiusY="6" />
                                                    </GeometryGroup>
                                                </Path.Data>
                                            </Path>
                                        </Grid>
                                    </Border>
                                </DataTemplate>
                            </telerik:SqlGeospatialDataReader.PointTemplate>
                        </telerik:SqlGeospatialDataReader>
                    </telerik:InformationLayer.Reader>
                    <telerik:InformationLayer.ShapeFill>
                        <telerik:MapShapeFill Fill="#7FFFFFFF" Stroke="#5A636B" StrokeThickness="3" />
                    </telerik:InformationLayer.ShapeFill>
                    <telerik:InformationLayer.HighlightFill>
                        <telerik:MapShapeFill Fill="#B2FFFFFF" Stroke="#5A636B" StrokeThickness="3" />
                    </telerik:InformationLayer.HighlightFill>
     
                </telerik:InformationLayer>
            </telerik:RadMap>
        </Grid>
    </UserControl>

    xaml.cs:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using Telerik.Windows.Controls.Map;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
     
    namespace ClosestCenter
    {
        public partial class MainPage : UserControl
        {
            private string VEKey;
            private WktDataRow lastHighlightedWkt;
            private FrameworkElement clickedElement;
            private MainPageViewModel context;
     
     
     
            public MainPage()
            {
                InitializeComponent();
     
                context = this.DataContext as MainPageViewModel;
     
                this.GetVEServiceKey();
     
                SetProvider();
            }
     
            private void SetProvider()
            {
                this.radMap.Provider = new BingMapProvider(MapMode.Aerial, true, this.VEKey);
            }
     
            private void Map_Loaded(object sender, RoutedEventArgs e)
            {
     
            }
     
            private object GetSenderDataPoint()
            {
                if (this.clickedElement != null)
                {
                    FrameworkElement element = this.clickedElement;
                    this.clickedElement = null;
     
                    return element.DataContext;
                }
     
                return null;
            }
     
            private CenterArea GetDataPointCenterArea(object senderDataPoint)
            {
                return (CenterArea)senderDataPoint;
            }
     
            private void radMap_MouseClick(object sender, MapMouseRoutedEventArgs eventArgs)
            {
                object senderDataPoint = GetSenderDataPoint();
                if (senderDataPoint != null)
                {
                    CenterArea ca = this.GetDataPointCenterArea(senderDataPoint);
     
                    this.SelectCenterArea(ca);
                }
            }
     
            private void SelectCenterArea (CenterArea ca)
            {
                this.context.Selection.SelectedCenterArea = ca;
            }
     
            private void elementMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
                FrameworkElement element = sender as FrameworkElement;
                if (element != null)
                {
                    this.clickedElement = element;
                }
            }
     
            private void GetVEServiceKey()
            {
                WebClient wc = new WebClient();
                wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_DownloadStringCompleted);
                Uri keyURI = new Uri(URIHelper.CurrentApplicationURL, "VEKey.txt");
                wc.DownloadStringAsync(keyURI);
            }
     
            void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
            {
                this.VEKey = e.Result;
                this.SetProvider();
            }
        }
    }

    Thanks,

    Tim







  3. DevCraft banner
  4. Andrey
    Admin
    Andrey avatar
    1681 posts

    Posted 28 Feb 2014 Link to this post

    Hi Tim,

    The MapMouseClick is an event of the RadMap control. So "sender" in the radMap_MouseClick is the RadMap control but not a map shape or point. So you definitely can't get WktDataRow from it. The same is true for the MouseLeftButtonDown which is set up on the InformationLayer. But in this case the sender will be an InformationLayer object.

    There are 2 visualization engines in the RadMap package.

    The old implementation of the map objects' (points and shapes) visualization consists of 3 layers: InformationLayer, DynamicLayer and VirtualizationLayer. This visualization engine, however, lacks certain features and has a few performance issues.

    In the Q2 2013 release we've introduced a new visualization engine in the RadMap. It has been designed from scratch to have better performance. The new visualization engine replaces all 3 layers with the new VisualizationLayer. The major goals of the new engine are:

    1. Improve the performance of the data visualization.
    2. Allow reading map shapes from different sources (KML, ESRI, and SQL Geospatial) in the background thread.
    3. Integrating clustering and items virtualization into the core. This simplifies the usage of both features.
    4. Ability to attach/detach almost any input event available for the FrameworkElement to the map shape visualization.
    5. Support of items selection in the engine core.

    I would recommend using the new engine (and its VisualizationLayer) instead of old one (or the InformationLayer).

    For more information I would recommend you to take a look at the following documentation topics:

    - Map Shape Data
    - Attaching input events to the map shapes
    - Shape Appearance
    - Reading Map Shapes

    When you get the MapShapeData in the MouseLeftButtonDown event handler then you can use its ExtendedData property. So, I think that you can find the WktDataRow object in your view model using some property which contains unique identifier of the WktDataRow object.

    Regards,
    Andrey Murzov
    Telerik

Back to Top