This is a migrated thread and some comments may be shown as answers.

Move MapItem on InformationLayer

6 Answers 282 Views
Map
This is a migrated thread and some comments may be shown as answers.
alireza
Top achievements
Rank 1
alireza asked on 07 Dec 2011, 12:31 PM
Hi
base on this tutorial :http://www.telerik.com/help/wpf/radmap-features-data-binding.html
I Implemented INotifyPropertyChange for MapItem
public class MapItem : INotifyPropertyChanged
{
    #region INotifyPropertyChanged Members
    void OnPropertyChanged(string prop)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, new PropertyChangedEventArgs(prop));
    }
 
    public event PropertyChangedEventHandler PropertyChanged;
and change their Location with this line of code
private void button1_Click(object sender, RoutedEventArgs e)
      {
          foreach (MapItem item in infLayerMovingObjects.ItemsSource)
          {
              Location loc = item.Location;
              loc.Latitude += 0.001;
              loc.Longitude += 0.001;
              item.Location = loc;
          }
      }

but it does not work ,
how should I have to Refresh LayerInformation ?
why LayerInformation does not notice about change in its obesrvable collection ?
thanks.

6 Answers, 1 is accepted

Sort by
0
Andrey
Telerik team
answered on 12 Dec 2011, 08:58 AM
Hi Alireza,

It is hard to say what is wrong with your implementation having just the code you've provided. Here it is an example of how it can be done. I hope it will help you understand the difference.

The data item class:

public class PointOfInterest : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
 
    private Location location;
    private string title;
    private string description;
 
    public Location Location
    {
        get
        {
            return this.location;
        }
 
        set
        {
            this.location = value;
            this.NotifyPropertyChanged("Location");
        }
    }
 
    public string Title
    {
        get
        {
            return this.title;
        }
 
        set
        {
            this.title = value;
            this.NotifyPropertyChanged("Title");
        }
    }
 
    public string Description
    {
        get
        {
            return this.description;
        }
 
        set
        {
            this.description = value;
            this.NotifyPropertyChanged("Description");
        }
    }
 
    protected void NotifyPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Main window XAML and code behind:

<UserControl x:Class="ClickablePinpoint.MainPage"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             mc:Ignorable="d"
             d:DesignHeight="300" d:DesignWidth="400">
     
    <UserControl.Resources>
        <DataTemplate x:Key="PoiTemplate">
            <Border telerik:MapLayer.Location="{Binding Location}"
                    Background="White"
                    BorderBrush="Black"
                    BorderThickness="1">
                <Grid Width="20" Height="20" Margin="5">
                    <TextBlock Grid.Row="0"
                               Text="{Binding Title}"
                               HorizontalAlignment="Center"
                               VerticalAlignment="Center"/>
                </Grid>
            </Border>
        </DataTemplate>
    </UserControl.Resources>
 
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
         
        <telerik:RadMap x:Name="radMap"
                        Center="42.5,-99"
                        ZoomLevel="7">
            <telerik:RadMap.Provider>
                <telerik:OpenStreetMapProvider />
            </telerik:RadMap.Provider>
            <telerik:InformationLayer x:Name="informationLayer"
                      ItemTemplate="{StaticResource PoiTemplate}" />
        </telerik:RadMap>
         
        <Button Grid.Column="1"
                VerticalAlignment="Top"
                Click="DoAction">
            <TextBlock Text="DoAction" />
        </Button>
    </Grid>
</UserControl>



public partial class MainPage : UserControl
{
    private ObservableCollection<PointOfInterest> collection = new ObservableCollection<PointOfInterest>();
 
    public MainPage()
    {
        InitializeComponent();
 
        // Add data points
        PointOfInterest poi = new PointOfInterest()
        {
            Location = new Location(41.5, -101),
            Title = "#1",
            Description = "Descr. #1"
        };
        collection.Add(poi);
 
        poi = new PointOfInterest()
        {
            Location = new Location(42, -100),
            Title = "#2",
            Description = "Descr. #2"
        };
        collection.Add(poi);
 
        poi = new PointOfInterest()
        {
            Location = new Location(42.5, -99),
            Title = "#3",
            Description = "Descr. #3"
        };
        collection.Add(poi);
 
        this.informationLayer.ItemsSource = collection;
    }
 
    private void DoAction(object sender, RoutedEventArgs e)
    {
        foreach (PointOfInterest poi in this.collection)
        {
            Location loc = poi.Location;
            loc.Latitude += 0.01;
            loc.Longitude += 0.01;
            poi.Location = loc;
        }
    }
}

If this doesn't helps, please, send us a simple application which demonstrates the problem you have so we could check what is wrong and help you.

All the best,
Andrey Murzov
the Telerik team

Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

0
SondreB
Top achievements
Rank 1
answered on 18 Jun 2013, 09:23 AM
This works fine for a normal InformationLayer, but using the ClusteredDataSource stops the changes to the properties to be visible in the map. After my push pin have first been rendered, I'm unable to move it or change it in any way by manipulating the object.

How would I go ahead and move a push pin rendered using the ClusteredDataSource? I'm not talking about the cluster pin, but the regular pins I'm showing when the user have zoomed the view.

Is there any way to fix this?
0
Andrey
Telerik team
answered on 18 Jun 2013, 10:52 AM
Hi Sondre,

It is very complicated and it is hard to reproduce the problem without your solution or code.
Could you, please, provide us with a small sample solution which reproduces it?

Regards,
Andrey Murzov
Telerik

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
SondreB
Top achievements
Rank 1
answered on 18 Jun 2013, 12:10 PM
Here is an attached example based upon the code above in this thread. I noticed another issue, and that is that the Title property is not binded properly as well, so that might be a clue. In the example, there are 6 points rendered, 3 of them binded directly to the InformationLayer, and the 3 others through a view model binded with the ClusteredDataSource. All items are rendered, but the 3 with ClusteredDataSource is missing it's Title and they don't move when the Location is changed.

Download the project source here: https://www.wetransfer.com/downloads/37074d9930467b1c4601731d03f60b9f20130618114532/f7ead64838af47551ce121d0a9ee72be20130618114532/7722be
0
Andrey
Telerik team
answered on 19 Jun 2013, 08:15 AM
Hello Sondre,

When you use the ClusteredDataSource for the InformationLayer then the items of the layer (clusters and single elements) are not updated automatically in a case when location of items which are bound to the ClusteredDataSource are updated. You should invoke the ClusteredDataSource.Refresh method after the items changed to refresh the layer. You can use a code like following at end of your DoAction method:
private void DoAction(object sender, RoutedEventArgs e)
{
    foreach (PointOfInterest poi in this.collection)
    {
        Location loc = poi.Location;
        loc.Latitude += 0.01;
        loc.Longitude += 0.01;
        poi.Location = loc;
    }
 
    var vm = (SomeViewModel)DataContext;
 
    foreach (PointOfInterest poi in vm.Items)
    {
        Location loc = poi.Location;
        loc.Latitude += 0.01;
        loc.Longitude += 0.01;
        poi.Location = loc;
    }
 
    this.pinsLayer.ClusteredDataSource.Refresh();
}

Also in a case with using the ClusteredDataSource the Title property should be bound using a path to the Data property. The sample data template is below.
<DataTemplate x:Key="PoiTemplate2">
    <Border telerik:MapLayer.Location="{Binding Location}"
            Background="White"
            BorderBrush="Black"
            BorderThickness="1">
        <Grid Width="20" Height="20" Margin="5">
            <TextBlock Grid.Row="0"
                       Text="{Binding Path=Data.Title}"
                       HorizontalAlignment="Center"
                       VerticalAlignment="Center"/>
        </Grid>
    </Border>
</DataTemplate>

Regards,
Andrey Murzov
Telerik

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
SondreB
Top achievements
Rank 1
answered on 19 Jun 2013, 11:48 AM
Great, thanks! Works perfectly :-)

Only one slight issue, I can no longer reuse the same DataTemplate when I have multiple layers with the same push pin template, due to the "Data." mapped property. Other than that, excellent!
Tags
Map
Asked by
alireza
Top achievements
Rank 1
Answers by
Andrey
Telerik team
SondreB
Top achievements
Rank 1
Share this question
or