No possibility to bind with RangeColorMapping

I have tried binding to RangeColorMapping in many ways. The application returns an error every time

The "Binding" element cannot be set in the "To" property of type "RangeColorMapping". So I changed my approach and tried with the code below, which works ... but very, very slow.

private void PrepareColorsForDataRanges()

        {

            var vm = DataContext as CountiesMapViewModel;

            var colorCount = _colorCodes.Length;

            var maxValue = vm.Report.Max(rp => rp.DataValue);

            var range = Convert.ToInt32(Math.Round(maxValue / colorCount));


            var shapeFileLayer = map.Layers[0] as ShapeFileLayer;

            var colorMappings = shapeFileLayer.ShapeSettings.FillSetting.ColorMappings;

            colorMappings.Clear();

            var zeroMapping = new RangeColorMapping();

            zeroMapping.From = 0;

            zeroMapping.To = 0;

            zeroMapping.Color = Colors.Transparent;

            colorMappings.Add(zeroMapping);

            int lastTo = 0;


            foreach (var cc in _colorCodes)

            {

                var from = lastTo;

                var to = lastTo + range;

                lastTo = to + 1;

                var mapping = new RangeColorMapping();

                mapping.From = from;

                mapping.To = to;

                mapping.Color = (Color)ColorConverter.ConvertFromString(cc);

                colorMappings.Add(mapping);

            }

        }


The next step to speed things up was to try to use ObservableCollection, 

        private void PrepareColorsForDataRanges()

        {

            List<RangeColorMapping> list = new List<RangeColorMapping>();


            var vm = DataContext as CountiesMapViewModel;

            var colorCount = _colorCodes.Length;

            var maxValue = vm.Report.Max(rp => rp.DataValue);

            var range = Convert.ToInt32(Math.Round(maxValue / colorCount));


            var shapeFileLayer = map.Layers[0] as ShapeFileLayer;

            var colorMappings = shapeFileLayer.ShapeSettings.FillSetting.ColorMappings;

            colorMappings.Clear();

            var zeroMapping = new RangeColorMapping();

            zeroMapping.From = 0;

            zeroMapping.To = 0;

            zeroMapping.Color = Colors.Transparent;


            list.Add(zeroMapping);

            int lastTo = 0;


            foreach (var cc in _colorCodes)

            {

                var from = lastTo;

                var to = lastTo + range;

                lastTo = to + 1;

                var mapping = new RangeColorMapping();

                mapping.From = from;

                mapping.To = to;

                mapping.Color = (Color)ColorConverter.ConvertFromString(cc);


                list.Add(mapping);

            }

            colorMappings = new ObservableCollection<ColorMapping>(list);

        }


but ColorMapping doesn't have set notifypropertychanged, so this approach doesn't work.

How can I bind the From and To property from code or xaml? Or how can I speed up the performance of generating maps with dynamic colors (depending on the data the map receives)


Best Regards

Piotr

 


8 Replies

ET Eswaran Thirugnanasambandam Syncfusion Team September 2, 2022 02:26 PM UTC

Query 1: The Binding element cannot be set in the "To" property of type RangeColorMapping.

We can reproduce the reported crash “System.Windows.Markup.XamlParseException” and we have considered it as internal bug. We will fix and include it in our upcoming weekly NuGet release, which is scheduled to be rolled out on September 6, 2022.


Query 2: When adding colormapping the map is very very slow.

We prepared a simple sample and checked the reported problem “The Map is very slow when adding the ColorMapping dynamically”, but we are unable to reproduce the reported problem from our side. Please check the tested sample from the below attachment. If you still face any problems, please revert us by modifying the sample based on your application scenario. It would be help us to provide an appropriate solution at the earliest.


Attachment: GettingStartedWPFMap_79f01628.zip


PI Piotr September 2, 2022 05:38 PM UTC

Thank you for your response. Then I will wait until Tuesday for the bug fix.




VR Vignesh Ramesh Syncfusion Team September 6, 2022 03:43 PM UTC

We have fixed the reported issue The Binding element cannot be set in the "To" property of type RangeColorMapping and the fix is included in our weekly NuGet of September 6, 2022. 


NuGet Version: v20.2.0.48


We thank you for your support and appreciate your patience in waiting for this release. Please get in touch with us if you require any further assistance.



PI Piotr September 6, 2022 06:12 PM UTC

Thank you! :)



PI Piotr replied to Piotr September 7, 2022 06:49 PM UTC

Unfortunately, I still have a performance issue. I mean, everything works for me, but extremely slow. A single map display takes about 120-140 seconds, and I do it on really strong equipment.

After your update, I did this:

in xaml I have the following code

<syncfusion:SfMap Grid.Row="2" x:Name="map">

                    <syncfusion:SfMap.Layers>

                        <syncfusion:ShapeFileLayer ItemsSource="{Binding Report}"

                                                   MapPopupVisibility="Visible"

                                                   ShapeIDPath="JPT_KOD_JE"

                                                   ShapeIDTableField="JPT_KOD_JE"

                                                   Uri="DB.UI.Resources.Maps.Powiaty.shp">

                            <syncfusion:ShapeFileLayer.Resources>

                                <helpers:BindingProxy

                                           x:Key="proxy"

                                           Data="{Binding}"/>

                            </syncfusion:ShapeFileLayer.Resources>

                            <syncfusion:ShapeFileLayer.ItemsTemplate>

                                <DataTemplate>

                                    <Grid Background="Transparent">

                                        <TextBlock Margin="5"

                                                   FontFamily="Segoe UI"

                                                   FontSize="12"

                                                   FontWeight="SemiBold"

                                                   Foreground="Black"

                                                   Opacity="1"

                                                   Text="{Binding Data.DataValue}" />

                                    </Grid>

                                </DataTemplate>

                            </syncfusion:ShapeFileLayer.ItemsTemplate>

                            <syncfusion:ShapeFileLayer.ShapeSettings>

                                <syncfusion:ShapeSetting ShapeColorValuePath="DataValue"

                                                         ShapeStrokeThickness="1"

                                                         ShapeValuePath="DataValue">

                                    <syncfusion:ShapeSetting.FillSetting>

                                        <syncfusion:ShapeFillSetting AutoFillColors="False">

                                            <syncfusion:ShapeFillSetting.ColorMappings>

                                                <syncfusion:RangeColorMapping To="0"

                                                                              From="0"

                                                                              Color="Transparent" />

                                                <syncfusion:RangeColorMapping To="{Binding Data.ToRange[0], Source={StaticResource proxy}}"

                                                                              From="{Binding Data.FromRange[0], Source={StaticResource proxy}}"

                                                                              Color="#ddb0b7" />

                                                <syncfusion:RangeColorMapping To="{Binding Data.ToRange[1], Source={StaticResource proxy}}"

                                                                              From="{Binding Data.FromRange[1], Source={StaticResource proxy}}"

                                                                              Color="#deacb3" />

                                                <syncfusion:RangeColorMapping To="{Binding Data.ToRange[2], Source={StaticResource proxy}}"

                                                                              From="{Binding Data.FromRange[2], Source={StaticResource proxy}}"

                                                                              Color="#e0a7af" />

                                                <syncfusion:RangeColorMapping To="{Binding Data.ToRange[3], Source={StaticResource proxy}}"

                                                                              From="{Binding Data.FromRange[3], Source={StaticResource proxy}}"

                                                                              Color="#e1a3ac" />

                                                <syncfusion:RangeColorMapping To="{Binding Data.ToRange[4], Source={StaticResource proxy}}"

                                                                              From="{Binding Data.FromRange[4], Source={StaticResource proxy}}"

                                                                              Color="#e29fa8" />

                                                <syncfusion:RangeColorMapping To="{Binding Data.ToRange[5], Source={StaticResource proxy}}"

                                                                              From="{Binding Data.FromRange[5], Source={StaticResource proxy}}"

                                                                              Color="#e49aa3" />

                                                <syncfusion:RangeColorMapping To="{Binding Data.ToRange[6], Source={StaticResource proxy}}"

                                                                              From="{Binding Data.FromRange[6], Source={StaticResource proxy}}"

                                                                              Color="#e5969f" />

                                                <syncfusion:RangeColorMapping To="{Binding Data.ToRange[7], Source={StaticResource proxy}}"

                                                                              From="{Binding Data.FromRange[7], Source={StaticResource proxy}}"

                                                                              Color="#e6929b" />

                                                <syncfusion:RangeColorMapping To="{Binding Data.ToRange[8], Source={StaticResource proxy}}"

                                                                              From="{Binding Data.FromRange[8], Source={StaticResource proxy}}"

                                                                              Color="#e68d97" />

                                                <syncfusion:RangeColorMapping To="{Binding Data.ToRange[9], Source={StaticResource proxy}}"

                                                                              From="{Binding Data.FromRange[9], Source={StaticResource proxy}}"

                                                                              Color="#e78992" />

                                                <syncfusion:RangeColorMapping To="{Binding Data.ToRange[10], Source={StaticResource proxy}}"

                                                                              From="{Binding Data.FromRange[10], Source={StaticResource proxy}}"

                                                                              Color="#e8848e" />

                                                <syncfusion:RangeColorMapping To="{Binding Data.ToRange[11], Source={StaticResource proxy}}"

                                                                              From="{Binding Data.FromRange[11], Source={StaticResource proxy}}"

                                                                              Color="#e88089" />

                                                <syncfusion:RangeColorMapping To="{Binding Data.ToRange[12], Source={StaticResource proxy}}"

                                                                              From="{Binding Data.FromRange[12], Source={StaticResource proxy}}"

                                                                              Color="#e97b84" />

                                                <syncfusion:RangeColorMapping To="{Binding Data.ToRange[13], Source={StaticResource proxy}}"

                                                                              From="{Binding Data.FromRange[13], Source={StaticResource proxy}}"

                                                                              Color="#e9767f" />

                                                <syncfusion:RangeColorMapping To="{Binding Data.ToRange[14], Source={StaticResource proxy}}"

                                                                              From="{Binding Data.FromRange[14], Source={StaticResource proxy}}"

                                                                              Color="#ea727b" />

                                                <syncfusion:RangeColorMapping To="{Binding Data.ToRange[15], Source={StaticResource proxy}}"

                                                                              From="{Binding Data.FromRange[15], Source={StaticResource proxy}}"

                                                                              Color="#ea6d76" />

                                                <syncfusion:RangeColorMapping To="{Binding Data.ToRange[16], Source={StaticResource proxy}}"

                                                                              From="{Binding Data.FromRange[16], Source={StaticResource proxy}}"

                                                                              Color="#ea6871" />

                                                <syncfusion:RangeColorMapping To="{Binding Data.ToRange[17], Source={StaticResource proxy}}"

                                                                              From="{Binding Data.FromRange[17], Source={StaticResource proxy}}"

                                                                              Color="#ea636b" />

                                                <syncfusion:RangeColorMapping To="{Binding Data.ToRange[18], Source={StaticResource proxy}}"

                                                                              From="{Binding Data.FromRange[18], Source={StaticResource proxy}}"

                                                                              Color="#ea5e66" />

                                                <syncfusion:RangeColorMapping To="{Binding Data.ToRange[19], Source={StaticResource proxy}}"

                                                                              From="{Binding Data.FromRange[19], Source={StaticResource proxy}}"

                                                                              Color="#e95961" />

                                                <syncfusion:RangeColorMapping To="{Binding Data.ToRange[20], Source={StaticResource proxy}}"

                                                                              From="{Binding Data.FromRange[20], Source={StaticResource proxy}}"

                                                                              Color="#e9535c" />

                                                <syncfusion:RangeColorMapping To="{Binding Data.ToRange[21], Source={StaticResource proxy}}"

                                                                              From="{Binding Data.FromRange[21], Source={StaticResource proxy}}"

                                                                              Color="#e94e56" />

                                                <syncfusion:RangeColorMapping To="{Binding Data.ToRange[22], Source={StaticResource proxy}}"

                                                                              From="{Binding Data.FromRange[22], Source={StaticResource proxy}}"

                                                                              Color="#e84851" />

                                                <syncfusion:RangeColorMapping To="{Binding Data.ToRange[23], Source={StaticResource proxy}}"

                                                                              From="{Binding Data.FromRange[23], Source={StaticResource proxy}}"

                                                                              Color="#e7434c" />

                                                <syncfusion:RangeColorMapping To="{Binding Data.ToRange[24], Source={StaticResource proxy}}"

                                                                              From="{Binding Data.FromRange[24], Source={StaticResource proxy}}"

                                                                              Color="#e73c46" />

                                                <syncfusion:RangeColorMapping To="{Binding Data.ToRange[25], Source={StaticResource proxy}}"

                                                                              From="{Binding Data.FromRange[25], Source={StaticResource proxy}}"

                                                                              Color="#e63640" />

                                                <syncfusion:RangeColorMapping To="{Binding Data.ToRange[26], Source={StaticResource proxy}}"

                                                                              From="{Binding Data.FromRange[26], Source={StaticResource proxy}}"

                                                                              Color="#e52f3b" />

                                                <syncfusion:RangeColorMapping To="{Binding Data.ToRange[27], Source={StaticResource proxy}}"

                                                                              From="{Binding Data.FromRange[27], Source={StaticResource proxy}}"

                                                                              Color="#e42735" />

                                                <syncfusion:RangeColorMapping To="{Binding Data.ToRange[28], Source={StaticResource proxy}}"

                                                                              From="{Binding Data.FromRange[28], Source={StaticResource proxy}}"

                                                                              Color="#e21d2f" />

                                                <syncfusion:RangeColorMapping To="{Binding Data.ToRange[29], Source={StaticResource proxy}}"

                                                                              From="{Binding Data.FromRange[29], Source={StaticResource proxy}}"

                                                                              Color="#e11029" />

                                            </syncfusion:ShapeFillSetting.ColorMappings>

                                        </syncfusion:ShapeFillSetting>

                                    </syncfusion:ShapeSetting.FillSetting>

                                </syncfusion:ShapeSetting>

                            </syncfusion:ShapeFileLayer.ShapeSettings>

                            <syncfusion:ShapeFileLayer.PopupCustomTemplate>

                                <DataTemplate>

                                    <Border>

                                        <Grid Width="250">

                                            <Grid.RowDefinitions>

                                                <RowDefinition />

                                                <RowDefinition />

                                                <RowDefinition />

                                            </Grid.RowDefinitions>

                                            <Grid.ColumnDefinitions>

                                                <ColumnDefinition />

                                            </Grid.ColumnDefinitions>

                                            <Border VerticalAlignment="Center"

                                                    Padding="10,5,0,0"

                                                    Height="30"

                                                    Background="#FF4B4A4A"

                                                    Grid.ColumnSpan="2">

                                                <TextBlock Foreground="White"

                                                           FontFamily="Segoe UI"

                                                           FontSize="14"

                                                           Text="{Binding CountyName}" />

                                            </Border>

                                            <Border Padding="3,10,3,3"

                                                    Background="White"

                                                    Grid.Row="1"

                                                    Grid.ColumnSpan="2">

                                                <StackPanel HorizontalAlignment="Center"

                                                            VerticalAlignment="Center"

                                                            Height="35"

                                                            Background="White"

                                                            Orientation="Horizontal">

                                                    <TextBlock Foreground="Black"

                                                               FontFamily="Segoe UI"

                                                               FontSize="16"

                                                               Text="{Binding TooltipDataValue}" />

                                                </StackPanel>

                                            </Border>

                                            <Border HorizontalAlignment="Center"

                                                    Grid.Row="2">

                                                <StackPanel Orientation="Horizontal">

                                                    <ItemsControl Background="White"

                                                                  ItemsSource="{Binding CountyName}"

                                                                  DisplayMemberPath="CountyName" />

                                                    <ItemsControl Background="White"

                                                                   ItemsSource="{Binding DataValue}"

                                                                   DisplayMemberPath="DataValue" />

                                                </StackPanel>

                                            </Border>

                                        </Grid>

                                    </Border>

                                </DataTemplate>

                            </syncfusion:ShapeFileLayer.PopupCustomTemplate>

                        </syncfusion:ShapeFileLayer>

                    </syncfusion:SfMap.Layers>

                </syncfusion:SfMap>


for this I have an auxiliary class:


 public class BindingProxy : Freezable

    {

        protected override Freezable CreateInstanceCore()

        {

            return new BindingProxy();

        }

        public object Data

        {

            get { return (object) GetValue(DataProperty); }

            set { SetValue(DataProperty, value); }

        }

        public static readonly DependencyProperty DataProperty =

            DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));

    }


and the rest in viewmodel

 public class CountiesMapViewModel : Screen

    {

        private CountiesDataProvider _countiesDataProvider = new CountiesDataProvider();

        private MapReportType _mapDataType = new MapReportType();


        public IEnumerable<MapData> Report => PrepareReportData();


        protected override Task OnInitializeAsync(CancellationToken token)

        {

            _counties = _countiesDataProvider.GetCounties;

            CountiesDataGrid = _counties;

            PrepareDataRanges();

            return Task.CompletedTask;

        }


        private IEnumerable<MapData> PrepareReportData()

        {

            IEnumerable<MapData> test = new List<MapData>();

            switch (SelectedReport)

            {

                case "Liczba Świadczeń":

                    test = from rows in _counties

                           select new MapData

                           {

                               JPT_KOD_JE = rows.JPT_KOD_JE,

                               CountyName = rows.County,

                               DataValue = rows.NumberOfMedicals,

                               TooltipDataValue = $"Liczba świadczeń: {rows.NumberOfMedicals}"

                           };

                    break;

                case "Liczba Pacjentów":

                    test = from rows in _counties

                           select new MapData

                           {

                               JPT_KOD_JE = rows.JPT_KOD_JE,

                               CountyName = rows.County,

                               DataValue = rows.NumberOfPatients,

                               TooltipDataValue = $"Liczba pacjentów: {rows.NumberOfPatients}"

                           };

                    break;

                case "Wartość Zrealizowanych Świadczeń":

                    test = from rows in _counties

                           select new MapData

                           {

                               JPT_KOD_JE = rows.JPT_KOD_JE,

                               CountyName = rows.County,

                               DataValue = rows.Execution,

                               TooltipDataValue = $"Wartość zrealizowanych świadczeń: {rows.Execution:C}"

                           };

                    break;

                case "Liczba Zrealizowanych Punktów":

                    test = from rows in _counties

                           select new MapData

                           {

                               JPT_KOD_JE = rows.JPT_KOD_JE,

                               CountyName = rows.County,

                               DataValue = rows.Points,

                               TooltipDataValue = $"Zrealizowane punkty: {rows.Points:N2}"

                           };

                    break;

            }


            return test;

        }


        private List<string> _reportType;

        public List<string> ReportType

        {

            get { return _mapDataType.ReportType; }

            set

            {

                _reportType = value;

                NotifyOfPropertyChange(() => ReportType);

                NotifyOfPropertyChange(() => Report);

            }

        }


        private string _selectedReport = "Liczba Świadczeń";


        public string SelectedReport

        {

            get { return _selectedReport; }

            set

            {

                _selectedReport = value;

                NotifyOfPropertyChange(() => SelectedReport);

                NotifyOfPropertyChange(() => Report);

                PrepareDataRanges();

            }

        }


        private IEnumerable<Counties> _counties;


        public IEnumerable<Counties> MapCounties

        {

            get { return _counties; }

            set

            {

                _counties = value;

                NotifyOfPropertyChange(() => MapCounties);

            }

        }


        public IEnumerable<Counties> CountiesDataGrid

        {

            get => _counties;

            set

            {

                _counties = value;

                NotifyOfPropertyChange(() => CountiesDataGrid);

            }

        }


        public void PrepareDataRanges()

        {

            var fromList = new List<int>();

            var toList = new List<int>();


            var maxValue = Report.Max(rp => rp.DataValue);

            var range = Convert.ToInt32(Math.Round(maxValue / 30));

            int lastTo = 0;

            for (int i = 0; i < 30; i++)

            {

                var from = lastTo;

                var to = lastTo + range;

                lastTo = to + 1;

                fromList.Add(from);

                toList.Add(to);

            }

            FromRange = new ObservableCollection<int>(fromList);

            ToRange = new ObservableCollection<int>(toList);

        }


        private ObservableCollection<int> _fromRange;

        public ObservableCollection<int> FromRange

        {

            get => _fromRange;

            set

            {

                _fromRange = value;

                NotifyOfPropertyChange(() => FromRange);

            }

        }


        private ObservableCollection<int> _toRange;

        public ObservableCollection<int> ToRange

        {

            get => _toRange;

            set

            {

                _toRange = value;

                NotifyOfPropertyChange(() => ToRange);

            }

        }

    }



BS Balachandar Selvam Syncfusion Team September 8, 2022 02:48 PM UTC

We prepared a sample based on the provided snippet and checked the reported problem: “A single map display takes about 120-140 seconds " by loading the world map with 30+ color mappings, but we are unable to reproduce the reported problem from our side. Please check the tested sample from the below attachment. If you still face any problems, please revert us by modifying the sample based on your application scenario and also please share the shape file if you have faced the problem with any particular shape file. It would help us to provide an appropriate solution at the earliest.


Attachment: GettingStartedMap_6723152f.zip


PI Piotr replied to Balachandar Selvam September 11, 2022 06:11 PM UTC

I have prepared a small example based on your project. I changed to the map I use plus I added a combobox for selecting the report. It loads quickly at startup, but it takes two minutes to change the report.

In the main project I also use the CaliburnMicro library, but it works just as slowly without it.


Attachment: Example_73e51331.7z


RS Ragul Subramani Syncfusion Team September 13, 2022 04:02 PM UTC

We validated the reported problem using the provided sample. Since the shape file contains nearly 300 shapes (polygons), each with a large number of points (more than 16K points). As a result, each polygon shape generation with a large number of points and rendering on the UI would probably take some time with each refresh and layout change on the windows.


This problem will also occur on normal shape rendering (with a large number of points) without using the SfMaps control.


Loader.
Up arrow icon