ClusteredDataSource Binding

3 posts, 0 answers
  1. Mehmet
    Mehmet avatar
    3 posts
    Member since:
    Jul 2012

    Posted 16 Jul 2012 Link to this post

    Hi,
    I'm developing an application that users can drag and drop items on a  radmap and move them around. I wanted to use ClusteredDataSource for drill down ability, but i'm struggling on binding the location property of my custom class.

    here is my custom object:
        public class ToolboxItem : ContentControl
        {
            public String IconPath { get; set; }

            public String Description { get; set; }

            public Location Location { get; set; }

        }

    And my ObservableCollection :

        public class ItemsDataSource : ObservableCollection<ToolboxItem>
        {
            Random rnd = new Random();

            public ItemsDataSource()
            {
                this.GeoBoundsNW = new Location(39, -120);
                this.GeoBoundsSE = new Location(32, -113);
                CreatePointsInRect(100);
            }

            private LocationRect dataRectangle = new LocationRect();
            public LocationRect DataRectangle
            {
                get { return dataRectangle; }
                set
                {
                    dataRectangle = value;
                }
            }

            private Location geoBoundsNW = Location.Empty;
            public Location GeoBoundsNW
            {
                get { return geoBoundsNW; }
                set
                {
                    geoBoundsNW = value;
                    UpdateGeoBounds();
                }
            }

            private Location geoBoundsSE = Location.Empty;
            public Location GeoBoundsSE
            {
                get { return geoBoundsSE; }
                set
                {
                    geoBoundsSE = value;
                    UpdateGeoBounds();
                }
            }

            private void UpdateGeoBounds()
            {
                if (!this.GeoBoundsNW.IsEmpty && !this.GeoBoundsSE.IsEmpty)
                {
                    this.DataRectangle = new LocationRect(this.GeoBoundsNW, this.GeoBoundsSE);
                }
            }

            #region Test
            private void CreatePointsInRect(int count)
            {
                if (!this.dataRectangle.IsEmpty)
                {
                    for (int i = 0; i < count; i++)
                    {
                        ToolboxItem item = new ToolboxItem();
                        Location loc = new Location(
                            this.DataRectangle.North - this.DataRectangle.GeoSize.Height * rnd.NextDouble(),
                            this.DataRectangle.West + this.DataRectangle.GeoSize.Width * rnd.NextDouble());
                        item.Name = "item" + i;
                        item.Location = loc;
                        
                        this.Add(item);
                    }
                }
            }
            #endregion

        }

    and my clustered data source defiifnition in xaml file:

                        <local:ItemsDataSource x:Key="ItemsDataSource" />

                        <telerik:ClusteredDataSource x:Key="clusteredDataSource"
                                                     ClusterItemTemplate="{StaticResource ClusterTemplate}"
                                                     ItemTemplate="{StaticResource ClusteredItemTemplate}"
                                                     GenerateClustersOnZoom="True"
                                                     ItemsSource="{StaticResource ItemsDataSource}">

                        </telerik:ClusteredDataSource>

    and of course my rad map control:

            <telerik:RadMap Name="radMap"
                            AllowDrop="True"
                            Grid.Column="2"
                            Grid.Row="1"
                            ZoomBarVisibility="Collapsed"
                            ZoomLevel="4"
                            Center="39,-120">
                <telerik:RadMap.Provider>
                    <telerik:OpenStreetMapProvider />
                </telerik:RadMap.Provider>
                <telerik:InformationLayer x:Name="infLayer" AllowDrop="True"
                                          ClusteredDataSource="{StaticResource clusteredDataSource}">
                </telerik:InformationLayer>
            </telerik:RadMap>

    and Clustered Item Template :
                        <DataTemplate x:Key="ClusteredItemTemplate">
                            <telerik:MapPinPoint telerik:MapLayer.Location= "{Binding Converter={StaticResource locConverter}}"
                                                 MouseLeftButtonUp="ClusteredItemMouseClick"/>
                        </DataTemplate>

    On data template i tried to bind Location property of my ToolboxItem but it was an unsuccessful attempt so then i provided an IValueConverter which is just below.

        public class LocationConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                var item = value as ClusteredItem;
                var toolboxItem = item.Data as ToolboxItem;

                return toolboxItem.Location;
            }

            public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                throw new NotImplementedException();
            }

        }


    The problem is if i change type of the ObservableCollection to Location it works perfectly, but i need to provide additional information for the visual and also for the status of the item. So i have to use my ToolboxItem as a type on my ObservableCollection, but i couldn't bind the Location property from toolboxItem.

    Does anybody have any idea how to do that.

    Thanks,

  2. Andrey
    Admin
    Andrey avatar
    1681 posts

    Posted 19 Jul 2012 Link to this post

    Hi Mehmet,

    The MapLayer.Location property in the clustered item template (ClusteredItemTemplate) should always be bound to the "Location" property of the ClusteredItem. In your data template it is bound to the "Location" property of the original data. I.e. the data template should look like this:

    <DataTemplate x:Key="ClusteredItemTemplate">
        <telerik:MapPinPoint telerik:MapLayer.Location="{Binding Path=Location}"
                 Text="{Binding Path=Data.Text}"
                 ImageSource="{Binding Path=Data.ImageSource}"
                 MouseLeftButtonUp="ClusteredItemMouseClick">
            <telerik:MapPinPoint.Background>
                <SolidColorBrush Color="Gray" Opacity="0.5" />
            </telerik:MapPinPoint.Background>
        </telerik:MapPinPoint>
    </DataTemplate>

    The ClusterItemGenerator has some automation to extract location from the data. But in the case of the arbitrary class (like it is in your code) generator can't do it without additional settings. You should inform it how to extract location from the custom object. For example:

    public MainWindow()
      
    {
        InitializeComponent();   
      
        // ...   
      
        ClusteredDataSource dataSource = this.informationLayer.ClusteredDataSource;
        ClusterItemGenerator generator = dataSource.ClusterItemGenerator as ClusterItemGenerator;
        generator.DataMappings.Add(new DataMapping("Location", DataMember.Location));   
      
        // ...  
    }


    Kind regards,
    Andrey Murzov
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  3. UI for WPF is Visual Studio 2017 Ready
  4. Mehmet
    Mehmet avatar
    3 posts
    Member since:
    Jul 2012

    Posted 19 Jul 2012 Link to this post

    Hi Andrey,

    Thanks for your reply, that really solved my problem.

    Have a nice day.
Back to Top