NotifyOfPropertyChange does not refresh the data in the map

Viewed 80

I have a problem refreshing the data after changing the report selected from combobox. In the ViewModel itself, the data changes, but the view does not refresh. Advice what am I doing wrong? Or what should I improve?

At the start, the data loads well and the map is colored, the only problem is changing the report and thus the lack of map refresh.

This is what I have at xaml:

<UserControl x:Class="DB.UI.Dashboard.NFZ.Maps.Views.CountiesMapView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:local="clr-namespace:DB.UI.Dashboard.NFZ.Maps.Views"
         xmlns:syncfusion="clr-namespace:Syncfusion.UI.Xaml.Maps;assembly=Syncfusion.SfMaps.WPF"
         xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
         xmlns:viewModels="clr-namespace:DB.UI.Dashboard.NFZ.Maps.ViewModels"
         mc:Ignorable="d"
         d:DesignHeight="450"
         d:DesignWidth="800"
         Loaded="CountiesMapView_OnLoaded">
<UserControl.Resources>
    <ResourceDictionary>
        <viewModels:CountiesMapViewModel x:Key="Vm"/>
    </ResourceDictionary>
</UserControl.Resources>
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="4*" />
    </Grid.ColumnDefinitions>
    <Grid Grid.Column="0">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <materialDesign:Card Grid.Row="0"
                             Foreground="Black"
                             Padding="8"
                             Margin="10 10 10 10"
                             UniformCornerRadius="6"
                             Background="White">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="auto" />
                    <RowDefinition Height="auto" />
                    <RowDefinition Height="*" />
                </Grid.RowDefinitions>
                <TextBlock Grid.Row="0"
                           TextAlignment="Center"
                           HorizontalAlignment="Center"
                           Text="Wybierz Raport"
                           TextWrapping="Wrap"
                           FontWeight="Bold"
                           FontSize="18"
                           ToolTip="Podsumowanie danych dla Realizatora&#x0a; w wybranym okresie rozliczeniowym" />
                <Separator Grid.Row="1"
                           Margin="5 0 5 10" />
                <ComboBox Grid.Row="2"
                          x:Name="ReportTypeComboBox"
                          Margin="5 0 5 10"
                          ItemsSource="{Binding ReportType}"
                          SelectedItem="{Binding SelectedReport}"
                          MinWidth="100"
                          HorizontalAlignment="Stretch"
                          HorizontalContentAlignment="Center">
                </ComboBox>
            </Grid>
        </materialDesign:Card>
    </Grid>
    <Grid Grid.Column="1">
        <materialDesign:Card Foreground="Black"
                             Padding="8"
                             Margin="10 10 10 10"
                             UniformCornerRadius="6"
                             Background="White">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="auto" />
                    <RowDefinition Height="auto" />
                    <RowDefinition Height="*" />
                </Grid.RowDefinitions>
                <TextBlock Grid.Row="0"
                           TextAlignment="Center"
                           HorizontalAlignment="Center"
                           Text="Powiaty"
                           TextWrapping="Wrap"
                           FontWeight="Bold"
                           FontSize="18"
                           ToolTip="Podsumowanie danych dla Realizatora&#x0a; w wybranym okresie rozliczeniowym" />
                <Separator Grid.Row="1"
                           Margin="5 0 5 10" />
                <syncfusion:SfMap Grid.Row="2"
                                  x:Name="map"
                                  DataContext="{StaticResource Vm}">
                    <syncfusion:SfMap.Layers>
                        <syncfusion:ShapeFileLayer ItemsSource="{Binding Report}"
                                                   MapPopupVisibility="Visible"
                                                   ShapeIDPath="CountyId"
                                                   ShapeIDTableField="JPT_KOD_JE"
                                                   Uri="DB.UI.Resources.Maps.Powiaty.shp">
                            <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 ToRange[0], Source={StaticResource Vm}}"
                                                                              From="{Binding FromRange[0], Source={StaticResource Vm}}"
                                                                              Color="#ddb0b7" />
                                                <syncfusion:RangeColorMapping To="{Binding ToRange[1], Source={StaticResource Vm}}"
                                                                              From="{Binding FromRange[1], Source={StaticResource Vm}}"
                                                                              Color="#deacb3" />
                                                <syncfusion:RangeColorMapping To="{Binding ToRange[2], Source={StaticResource Vm}}"
                                                                              From="{Binding FromRange[2], Source={StaticResource Vm}}"
                                                                              Color="#e0a7af" />
                                                <syncfusion:RangeColorMapping To="{Binding ToRange[3], Source={StaticResource Vm}}"
                                                                              From="{Binding FromRange[3], Source={StaticResource Vm}}"
                                                                              Color="#e1a3ac" />
                                                <syncfusion:RangeColorMapping To="{Binding ToRange[4], Source={StaticResource Vm}}"
                                                                              From="{Binding FromRange[4], Source={StaticResource Vm}}"
                                                                              Color="#e29fa8" />
                                                <syncfusion:RangeColorMapping To="{Binding ToRange[5], Source={StaticResource Vm}}"
                                                                              From="{Binding FromRange[5], Source={StaticResource Vm}}"
                                                                              Color="#e49aa3" />
                                                <syncfusion:RangeColorMapping To="{Binding ToRange[6], Source={StaticResource Vm}}"
                                                                              From="{Binding FromRange[6], Source={StaticResource Vm}}"
                                                                              Color="#e5969f" />
                                                <syncfusion:RangeColorMapping To="{Binding ToRange[7], Source={StaticResource Vm}}"
                                                                              From="{Binding FromRange[7], Source={StaticResource Vm}}"
                                                                              Color="#e6929b" />
                                                <syncfusion:RangeColorMapping To="{Binding ToRange[8], Source={StaticResource Vm}}"
                                                                              From="{Binding FromRange[8], Source={StaticResource Vm}}"
                                                                              Color="#e68d97" />
                                                <syncfusion:RangeColorMapping To="{Binding ToRange[9], Source={StaticResource Vm}}"
                                                                              From="{Binding FromRange[9], Source={StaticResource Vm}}"
                                                                              Color="#e78992" />
                                                <syncfusion:RangeColorMapping To="{Binding ToRange[10], Source={StaticResource Vm}}"
                                                                              From="{Binding FromRange[10], Source={StaticResource Vm}}"
                                                                              Color="#e8848e" />
                                                <syncfusion:RangeColorMapping To="{Binding ToRange[11], Source={StaticResource Vm}}"
                                                                              From="{Binding FromRange[11], Source={StaticResource Vm}}"
                                                                              Color="#e88089" />
                                                <syncfusion:RangeColorMapping To="{Binding ToRange[12], Source={StaticResource Vm}}"
                                                                              From="{Binding FromRange[12], Source={StaticResource Vm}}"
                                                                              Color="#e97b84" />
                                                <syncfusion:RangeColorMapping To="{Binding ToRange[13], Source={StaticResource Vm}}"
                                                                              From="{Binding FromRange[13], Source={StaticResource Vm}}"
                                                                              Color="#e9767f" />
                                                <syncfusion:RangeColorMapping To="{Binding ToRange[14], Source={StaticResource Vm}}"
                                                                              From="{Binding FromRange[14], Source={StaticResource Vm}}"
                                                                              Color="#ea727b" />
                                                <syncfusion:RangeColorMapping To="{Binding ToRange[15], Source={StaticResource Vm}}"
                                                                              From="{Binding FromRange[15], Source={StaticResource Vm}}"
                                                                              Color="#ea6d76" />
                                                <syncfusion:RangeColorMapping To="{Binding ToRange[16], Source={StaticResource Vm}}"
                                                                              From="{Binding FromRange[16], Source={StaticResource Vm}}"
                                                                              Color="#ea6871" />
                                                <syncfusion:RangeColorMapping To="{Binding ToRange[17], Source={StaticResource Vm}}"
                                                                              From="{Binding FromRange[17], Source={StaticResource Vm}}"
                                                                              Color="#ea636b" />
                                                <syncfusion:RangeColorMapping To="{Binding ToRange[18], Source={StaticResource Vm}}"
                                                                              From="{Binding FromRange[18], Source={StaticResource Vm}}"
                                                                              Color="#ea5e66" />
                                                <syncfusion:RangeColorMapping To="{Binding ToRange[19], Source={StaticResource Vm}}"
                                                                              From="{Binding FromRange[19], Source={StaticResource Vm}}"
                                                                              Color="#e95961" />
                                                <syncfusion:RangeColorMapping To="{Binding ToRange[20], Source={StaticResource Vm}}"
                                                                              From="{Binding FromRange[20], Source={StaticResource Vm}}"
                                                                              Color="#e9535c" />
                                                <syncfusion:RangeColorMapping To="{Binding ToRange[21], Source={StaticResource Vm}}"
                                                                              From="{Binding FromRange[21], Source={StaticResource Vm}}"
                                                                              Color="#e94e56" />
                                                <syncfusion:RangeColorMapping To="{Binding ToRange[22], Source={StaticResource Vm}}"
                                                                              From="{Binding FromRange[22], Source={StaticResource Vm}}"
                                                                              Color="#e84851" />
                                                <syncfusion:RangeColorMapping To="{Binding ToRange[23], Source={StaticResource Vm}}"
                                                                              From="{Binding FromRange[23], Source={StaticResource Vm}}"
                                                                              Color="#e7434c" />
                                                <syncfusion:RangeColorMapping To="{Binding ToRange[24], Source={StaticResource Vm}}"
                                                                              From="{Binding FromRange[24], Source={StaticResource Vm}}"
                                                                              Color="#e73c46" />
                                                <syncfusion:RangeColorMapping To="{Binding ToRange[25], Source={StaticResource Vm}}"
                                                                              From="{Binding FromRange[25], Source={StaticResource Vm}}"
                                                                              Color="#e63640" />
                                                <syncfusion:RangeColorMapping To="{Binding ToRange[26], Source={StaticResource Vm}}"
                                                                              From="{Binding FromRange[26], Source={StaticResource Vm}}"
                                                                              Color="#e52f3b" />
                                                <syncfusion:RangeColorMapping To="{Binding ToRange[27], Source={StaticResource Vm}}"
                                                                              From="{Binding FromRange[27], Source={StaticResource Vm}}"
                                                                              Color="#e42735" />
                                                <syncfusion:RangeColorMapping To="{Binding ToRange[28], Source={StaticResource Vm}}"
                                                                              From="{Binding FromRange[28], Source={StaticResource Vm}}"
                                                                              Color="#e21d2f" />
                                                <syncfusion:RangeColorMapping To="{Binding ToRange[29], Source={StaticResource Vm}}"
                                                                              From="{Binding FromRange[29], Source={StaticResource Vm}}"
                                                                              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 DataValue}"
                                                                  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>
            </Grid>
        </materialDesign:Card>
    </Grid>
</Grid>

and this is in ViewModel

public class CountiesMapViewModel : Screen
{
    private CountiesDataProvider _countiesDataProvider = new CountiesDataProvider();
    private MapReportType _mapDataType = new MapReportType();

    private ObservableCollection<MapData> _report;

    public ObservableCollection<MapData> Report
    {
        get { return _report; }
        set 
        { 
            _report = value; 
            NotifyOfPropertyChange(() => Report);
        }
    }
    private IEnumerable<Counties> _counties;
    public IEnumerable<Counties> Counties
    {
        get { return _counties; }
        set
        {
            _counties = value;
            NotifyOfPropertyChange(() => Counties);
        }
    }

    private ObservableCollection<int> _fromRange;

    public ObservableCollection<int> FromRange
    {
        get { return _fromRange; }
        set
        {
            _fromRange = value;
            NotifyOfPropertyChange(() => FromRange);
        }
    }

    private ObservableCollection<int> _toRange;

    public ObservableCollection<int> ToRange
    {
        get { return _toRange; }
        set
        {
            _toRange = value;
            NotifyOfPropertyChange(() => ToRange);
        }
    }

    public CountiesMapViewModel()
    {
        _counties = _countiesDataProvider.GetCounties;
        Report = new ObservableCollection<MapData>(PrepareReportData(_counties));
        PrepareDataRanges(Report.Max(rp => rp.DataValue));
    }

    public void PrepareDataRanges(decimal maxValue)
    {
        var fromList = new List<int>();
        var toList = new List<int>();

        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<MapData> PrepareReportData(IEnumerable<Counties> counties)
    {
        ObservableCollection<MapData> prepareReportData = new ObservableCollection<MapData>();
        switch (SelectedReport)
        {
            case "Liczba Świadczeń":
                foreach (var row in counties)
                {
                    prepareReportData.Add(new MapData()
                    {
                        CountyId = row.CountyId,
                        CountyName = row.County,
                        DataValue = row.NumberOfMedicals,
                        TooltipDataValue = $"Liczba świadczeń: {row.NumberOfMedicals}"
                    });
                }
                break;
            case "Liczba Pacjentów":
                foreach (var row in counties)
                {
                    prepareReportData.Add(new MapData()
                    {
                        CountyId = row.CountyId,
                        CountyName = row.County,
                        DataValue = row.NumberOfPatients,
                        TooltipDataValue = $"Liczba Pacjentów: {row.NumberOfPatients}"
                    });
                }
                break;
            case "Wartość Zrealizowanych Świadczeń":
                foreach (var row in counties)
                {
                    prepareReportData.Add(new MapData()
                    {
                        CountyId = row.CountyId,
                        CountyName = row.County,
                        DataValue = row.Execution,
                        TooltipDataValue = $"Wartość zrealizowanych świadczeń: {row.Execution:C}"
                    });
                }
                break;
            case "Liczba Zrealizowanych Punktów":
                foreach (var row in counties)
                {
                    prepareReportData.Add(new MapData()
                    {
                        CountyId = row.CountyId,
                        CountyName = row.County,
                        DataValue = row.Points,
                        TooltipDataValue = $"Zrealizowane punkty: {row.Points:N2}"
                    });
                }
                break;
        }
        return prepareReportData;
    }
    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);

            Report = new ObservableCollection<MapData>(PrepareReportData(_counties));
            PrepareDataRanges(Report.Max(rp => rp.DataValue));
            NotifyOfPropertyChange(() => Report);
        }
    }
}
public class MapData
{
    public int CountyId { get; set; }
    public string CountyName { get; set; }
    public decimal DataValue { get; set; }
    public string TooltipDataValue { get; set; }
}

I'm using CaliburnMicro and syncfusion for Map.

1 Answers

A couple of things

  1. The combobox is bound to nothing, so when a new value selected for the combobx, the code in the setter of SelectedReport is not executed

This is because you are setting the DataContext for the Map control only, so let's change the way view-viewmodel linkup

  1. Replace
<UserControl.Resources>
    <ResourceDictionary>
        <local:CountiesMapViewModel x:Key="Vm" />
    </ResourceDictionary>
</UserControl.Resources>

With

<UserControl.DataContext>
    <local:CountiesMapViewModel/>
</UserControl.DataContext>

Therefore, CountiesMapViewModel will be the DataContext for all of the UserControl.

Now, Remove all the occurrences of DataContext="{StaticResource Vm}" And , Source={StaticResource Vm} in '.xaml', no need for these at all (the second one is not even needed in your old code)

Give it a try..

Related