Bind MapShapeData fill color

7 posts, 1 answers
  1. Etienne
    Etienne avatar
    47 posts
    Member since:
    Sep 2014

    Posted 30 Jul 2015 Link to this post

    Hi,

    Is there a way to bind the fill color of a map shape to a property of my DataContext but I can't do it. Here's what I've tried:

    <DataTemplate x:Key="FooTemplate" DataType="Foo">
        <telerik:MapPathView>
            <telerik:MapPathView.Data>
                <tmpl:FooView .../>
            </telerik:MapPathView.Data>
            <telerik:MapPathView.ShapeFill>
                <telerik:MapShapeFill Fill="{Binding SomeProperty, Converter={StaticResource SomePropertyToBrushConverter}}" StrokeThickness="1"/>
            </telerik:MapPathView.ShapeFill>
        </telerik:MapPathView>
    </DataTemplate>

    When I run, I have an error "Cannot find source for binding with reference ..." because MapSahpeFill doesn't inherit the "inheritance context".

    So is there a way to achieve what I want ?

    Thank you,

    Etienne

  2. Martin
    Admin
    Martin avatar
    1101 posts

    Posted 04 Aug 2015 Link to this post

    Hello Etienne,

    I am afraid that since the MapPathView element it is not presented in the visual tree and it doesn't inherit the data context for its content presenter, the Stroke property of the MapShapeFill cannot be bound. In order to achieve your requirement you can define a MapShapeFill property in your view model and try to bind it to the ShapeFill property of the MapPathView.
    <telerik:MapPathView ShapeFill="{Binding FlightPathFillDescription}">
    You can also consider using a FrameworkElement directly instead of the map's bindable wrappers. For example:
    <Path Fill="{Binding SomeProperty, Converter={StaticResource SomePropertyToBrushConverter}"
          telerik:MapLayer.Location="{Binding Location}">
        <Path.Data>
            <!-- define the path data -->
        </Path.Data>   
    </telerik:MapPathView>
    Using this approach the you will need to recalculate the path's data each time the zoom level is changed since it it define in pixels. You can convert Point to Location you can use the Location.GetCoordinates() static method.

    I hope this information helps.

    Regards,
    Martin
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  3. UI for WPF is Visual Studio 2017 Ready
  4. Etienne
    Etienne avatar
    47 posts
    Member since:
    Sep 2014

    Posted 04 Aug 2015 in reply to Martin Link to this post

    Hi Martin,

    Thank you for your answer, I've tried the first solution (ShapeFill bound to a property in the view model) but it doesn't work well. The ShapeFill is not updated immediately when the property in my view model is updated. I must zoom a lot and move the map to see the change of the fill color being applied.

    Also, do you have an example for the second solution, I'm not sure how to do that.

    Thank you,

    Etienne

  5. Answer
    Martin
    Admin
    Martin avatar
    1101 posts

    Posted 07 Aug 2015 Link to this post

    Hi Etienne,

    In order for the ShapeFill to be updated properly you will need to write some custom code. Basically, you can use an attached property and in its OnPropertyChangedCallback method you can set the shape fill to the wrapper. Then call the UseRegularFill() method of the wrapper's ShapeData. Here is an example:
    public class MapUtilities
    {
        public static MapShapeFill GetShapeFill(DependencyObject obj)
        {
            return (MapShapeFill)obj.GetValue(ShapeFillProperty);
        }
     
        public static void SetShapeFill(DependencyObject obj, MapShapeFill value)
        {
            obj.SetValue(ShapeFillProperty, value);
        }
     
        public static readonly DependencyProperty ShapeFillProperty =
            DependencyProperty.RegisterAttached("ShapeFill", typeof(MapShapeFill), typeof(MapUtilities), new PropertyMetadata(null, OnShapeFillChanged));
     
        private static void OnShapeFillChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {  
            var wrapper = (MapShapeBindableWrapper)d;
            if (e.NewValue != null)
            {
                wrapper.ShapeFill = (MapShapeFill)e.NewValue;
                var shapeData = wrapper.ShapeData;
                shapeData.UseRegularFill();
            }          
        }
    }

    <DataTemplate x:Key="FooTemplate" DataType="Foo" local:MapUtilities.ShapeFill="{Binding FlightPathFillDescription}">
        <telerik:MapPathView>
            <telerik:MapPathView.Data>
                <tmpl:FooView .../>
            </telerik:MapPathView.Data>
        </telerik:MapPathView>
    </DataTemplate>
    I also attached a sample project demonstrating this approach. Please give it a try and let me know if it works for you.

    As for the second solution, currently I do not have an example with this approach.

    Regards,
    Martin
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  6. Etienne
    Etienne avatar
    47 posts
    Member since:
    Sep 2014

    Posted 07 Aug 2015 in reply to Martin Link to this post

    Hi Martin,

    Thank you for the solution, it works great! I don't know why it haven't been done this way in the first time, but think it would be nice if the ShapeFill property of MapShapeBindableWrapper had the same behavior then the one you made in MapUtilities.

    Thanks again!

    Etienne

  7. Luke
    Luke avatar
    9 posts
    Member since:
    Jan 2015

    Posted 04 Apr Link to this post

    Good Morning Petar

    This perhaps is getting complicated for my simple needs.  All I want to do is change the colour of a given country

    How I was doing previously with the Information layer was looping through all the shape names until the one I wanted was found, then adjusting its fill colour inside the loop.

    To reset all the colours, I did the same, but without singling out a particular country, and adjusting all of their fill colours.

    I would be quite happy to do the same, but its accessing each country that is the problem (and why I changed direction and thought I could bind a colour from the model).

    Is there any simple solution for changing country colours in the back end with a visulization layer driver by SQL shape data – I image the countries exist somehow as an individual entity as they are an individually selectable.

    Thanks
  8. Petar Mladenov
    Admin
    Petar Mladenov avatar
    2891 posts

    Posted 05 Apr Link to this post

    Hello,

    I have modified our ManualShapeReading SDK sample in the following way:
                    -- Informationlayer is replaced with VisualizationLayer
                    -- ShapeReader is replaced with AsyncShapeFileReader
                    --When read is complete - all shape objects's indices are stored a dictionary in format <countryName, index>
                    -- On a Button Click the Russia's shape ShapeFill is changed runtime. Please note here that if you change the ShapeFill, HighlightFill or SelectedFill properties then you need to use UseRegularFill / UseHighlightFill / Use SelectedFill methods. These 3 methods change the ActualShapeFill internal property which is bound in the template of the shapes.

    We hope the solution will help you move forward.


    Regards,
    Petar Mladenov
    Telerik
    Do you need help with upgrading your AJAX, WPF or WinForms project? Check the Telerik API Analyzer and share your thoughts.
Back to Top
UI for WPF is Visual Studio 2017 Ready