WPF IModule, IRegionManage,ContentRegion, MVVM, LiveCharts,PieChart,CartesianChart

Get-Project -All|Install-Package livecharts.wpf
Get-Project -All|Install-Package Prism.DryIoc -version 8.1.97
Get-Project -All|Install-Package Prism.Wpf -version 8.1.97


//Shell.App.xaml
<prism:PrismApplication x:Class="Shell.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:Shell"
             xmlns:prism="http://prismlibrary.com/">
</prism:PrismApplication>

//Shell.App.xaml.cs
using CanadaModule;
using LiveCharts.Wpf;
using Prism.DryIoc;
using Prism.Ioc;
using Prism.Modularity;
using System.Configuration;
using System.Data;
using System.Reflection;
using System.Windows;
using System.Windows.Shapes;

namespace Shell
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : PrismApplication
    {
        protected override Window CreateShell()
        {
            return Container.Resolve<MainWindow>();
        }

        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            //注冊mock数据服务
            containerRegistry.RegisterSingleton<Shared.Services.MockDataService>(() => Shared.Services.MockDataService.Instance);
        }

        protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
        {
            moduleCatalog.AddModule<HomeModule.HomeModule>();
            moduleCatalog.AddModule<USAModule.USAModule>();
            moduleCatalog.AddModule<CanadaModule.CanadaModule>();
            moduleCatalog.AddModule<AustraliaModule.AustraliaModule>();
            moduleCatalog.AddModule<UKModule.UKModule>();
            base.ConfigureModuleCatalog(moduleCatalog);
        }
    }

}

//MainWindow.xaml
<Window x:Class="Shell.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Shell"
        xmlns:prism="http://www.codeplex.com/prism"
        prism:ViewModelLocator.AutoWireViewModel="True"
        WindowState="Maximized"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <local:ViewNameMatchConverter x:Key="ViewNameMatchConverter"/>

        <!-- 2. 修正导航按钮样式(用MultiDataTrigger替代原DataTrigger) -->
        <Style x:Key="NavButtonStyle" TargetType="Button">
            <Setter Property="Height" Value="50"/>
            <Setter Property="Background" Value="#34495E"/>
            <Setter Property="Foreground" Value="White"/>
            <Setter Property="FontSize" Value="30"/>
            <Setter Property="Padding" Value="10 5"/>
            <Setter Property="BorderThickness" Value="0"/>
            <Setter Property="HorizontalAlignment" Value="Stretch"/>
            <Setter Property="FontWeight" Value="Normal"/>
            <Style.Triggers>
                <!-- 原有鼠标悬浮效果 -->
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Background" Value="#1ABC9C"/>
                    <Setter Property="Height" Value="70"/>
                </Trigger>

                <!-- 核心:MultiDataTrigger实现选中高亮(解决Value不能绑定的问题) -->
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition>
                            <Condition.Binding>
                                <!-- 多值绑定:同时传当前视图名 + 按钮参数 -->
                                <MultiBinding Converter="{StaticResource ViewNameMatchConverter}">
                                    <!-- 绑定窗口ViewModel的CurrentViewName -->
                                    <Binding RelativeSource="{RelativeSource AncestorType=Window}" 
                                             Path="DataContext.CurrentViewName"/>
                                    <!-- 绑定当前按钮的CommandParameter -->
                                    <Binding RelativeSource="{RelativeSource Self}" 
                                             Path="CommandParameter"/>
                                </MultiBinding>
                            </Condition.Binding>
                            <Condition.Value>True</Condition.Value>
                        </Condition>
                    </MultiDataTrigger.Conditions>

                    <!-- 选中高亮样式(可自定义) -->
                    <Setter Property="Background" Value="Cyan"/>
                    <!-- 红色背景 -->
                    <Setter Property="Height" Value="70"/>
                    <!-- 高度放大 -->
                    <Setter Property="FontWeight" Value="Bold"/>
                    <!-- 字体加粗 -->
                    <Setter Property="Foreground" Value="Yellow"/>
                    <!-- 黄色字体 -->
                    <Setter Property="BorderBrush" Value="White"/>
                    <!-- 白色边框 -->
                    <Setter Property="BorderThickness" Value="2"/>
                    <!-- 边框宽度 -->
                </MultiDataTrigger>
            </Style.Triggers>
        </Style>


        <!--<Style x:Key="NavButtonStyle" TargetType="Button">
            <Setter Property="Height" Value="50"/>
            <Setter Property="Background" Value="#34495E"/>
            <Setter Property="Foreground" Value="White"/>
            <Setter Property="FontSize" Value="30"/>
            <Setter Property="Padding" Value="10 5"/>
            <Setter Property="BorderThickness" Value="0"/>
            <Setter Property="HorizontalAlignment" Value="Stretch"/>
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Background" Value="#1ABC9C"/>
                    <Setter Property="Height" Value="70"/>
                </Trigger>
                -->
        <!-- 核心:选中高亮触发 -->
        <!--
                <DataTrigger                    
                    Binding="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.CurrentViewName}"
                    Value="{Binding RelativeSource={RelativeSource Self}, Path=CommandParameter}">
                    -->
        <!-- 高亮样式(可自定义) -->
        <!--
                    <Setter Property="Background" Value="#E74C3C"/>
                    -->
        <!-- 红色高亮 -->
        <!--
                    <Setter Property="Height" Value="70"/>
                    -->
        <!-- 高度放大 -->
        <!--
                    <Setter Property="FontWeight" Value="Bold"/>
                    -->
        <!-- 字体加粗 -->
        <!--
                    <Setter Property="Foreground" Value="Yellow"/>
                    -->
        <!-- 字体黄色 -->
        <!--
                    <Setter Property="BorderBrush" Value="White"/>
                    -->
        <!-- 白色边框 -->
        <!--
                    <Setter Property="BorderThickness" Value="2"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>-->

        <Style TargetType="TextBlock">
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Background" Value="#1ABC9C"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <Grid>
        <!--左侧导航栏-->
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="200"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <!--导航菜单-->
        <StackPanel Grid.Column="0" Background="#2C3E50" Margin="10">
            <TextBlock Text="导航菜单" FontSize="36" Foreground="White"
                       HorizontalAlignment="Center"/>
            <Button Content="首页" Command="{Binding NavigateCommand}"
                    CommandParameter="HomeView" Style="{StaticResource NavButtonStyle}"
                    Margin="0"/>
            <Button Content="USA" Command="{Binding NavigateCommand}"
                    CommandParameter="USAView" Style="{StaticResource NavButtonStyle}"
                    Margin="0"/>
            <Button Content="Canada" Command="{Binding NavigateCommand}"
                    CommandParameter="CanadaView" Style="{StaticResource NavButtonStyle}"
                    Margin="0"/>
            <Button Content="Australia" Command="{Binding NavigateCommand}"
                    CommandParameter="AustraliaView" Style="{StaticResource NavButtonStyle}"
                    Margin="0"/>
            <Button Content="UK" Command="{Binding NavigateCommand}"
                    CommandParameter="UKView" Style="{StaticResource NavButtonStyle}"
                    Margin="0"/>
        </StackPanel>

        <ContentControl Grid.Column="1"
                        prism:RegionManager.RegionName="ContentRegion"
                        Margin="2"/>
    </Grid>
</Window>

//MainWindowViewModel.cs
using Prism.Commands;
using Prism.Mvvm;
using Prism.Regions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Shell
{
    public class MainWindowViewModel : BindableBase
    {
        private readonly IRegionManager regionManager;

        // 跟踪当前选中的视图名称(初始为HomeView,默认高亮首页)
        private string _currentViewName = "HomeView";
        public string CurrentViewName
        {
            get => _currentViewName;
            set => SetProperty(ref _currentViewName, value); // 触发UI更新
        }

        public DelegateCommand<string> NavigateCommand { get; }
        public MainWindowViewModel(IRegionManager regionManagerValue)
        {
            regionManager = regionManagerValue;
            NavigateCommand = new DelegateCommand<string>(NavigateCommandExecuted);
            NavigateCommandExecuted("HomeView");
        }

        private void NavigateCommandExecuted(string viewName)
        {
            if (string.IsNullOrEmpty(viewName))
            {
                return;
            }

            // 1. 导航到指定视图
            regionManager.RequestNavigate("ContentRegion", viewName);
            // 2. 更新当前选中视图名称(用于按钮高亮)
            CurrentViewName = viewName;
        }
    }
}
//ViewNameMatchConverter.cs
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;

namespace Shell
{
    /// <summary>
    /// 比较当前视图名和按钮参数是否一致的转换器
    /// </summary>
    public class ViewNameMatchConverter : IMultiValueConverter
    {
        /// <summary>
        /// 转换逻辑:value[0]=CurrentViewName,value[1]=CommandParameter
        /// </summary>
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            // 校验参数完整性
            if (values.Length < 2 || values[0] == null || values[1] == null)
                return false;

            // 比较两个值是否相等(忽略大小写)
            string currentView = values[0].ToString();
            string buttonParam = values[1].ToString();
            return currentView.Equals(buttonParam, StringComparison.Ordinal);
        }

        // 反向转换无需实现(导航选中状态无需反向修改)
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException("无需反向转换");
        }
    }
}

 

image

 

image

 

 

image

 

 

 

 

 

 

image

 

 

 

image

 

 

 

//Shared Module
using Shared.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Shared.Services
{
    /// <summary>
    /// 模拟数据服务(单例)
    /// </summary>
    public class MockDataService
    {
        private static readonly Lazy<MockDataService> _instance = new(() => new MockDataService());
        public static MockDataService Instance => _instance.Value;

        // 获取指定国家的完整数据
        public CountryStatsModel GetCountryData(string countryName)
        {
            return countryName.ToLower() switch
            {
                "usa" => GetUSAData(),
                "canada" => GetCanadaData(),
                "australia" => GetAustraliaData(),
                "uk" => GetUKData(),
                _ => GetHomeData() // 首页默认展示汇总
            };
        }

        #region 各国家Mock数据实现
        private CountryStatsModel GetUSAData()
        {
            return new CountryStatsModel
            {
                CountryName = "USA",
                Population = 334998398,
                PerCapitaIncome = 76398.23m,
                Area = 9833517.0,
                GDP = 26.854m,
                Capital = "Washington, D.C.",
                LargestCity = "New York City",
                RDSpending = 3.51m,

                // 人种构成(饼图)
                DemographicData = new List<DemographicData>
                {
                    new() { Ethnicity = "White", Percentage = 57.8 },
                    new() { Ethnicity = "Hispanic/Latino", Percentage = 18.7 },
                    new() { Ethnicity = "Black", Percentage = 13.6 },
                    new() { Ethnicity = "Asian", Percentage = 6.0 },
                    new() { Ethnicity = "Other", Percentage = 3.9 }
                },

                // 年龄趋势(折线图)
                AgeTrendData = new List<AgeTrendData>
                {
                    new() { AgeGroup = 0, PopulationRatio = 1.2 },
                    new() { AgeGroup = 10, PopulationRatio = 1.8 },
                    new() { AgeGroup = 20, PopulationRatio = 2.1 },
                    new() { AgeGroup = 30, PopulationRatio = 2.3 },
                    new() { AgeGroup = 40, PopulationRatio = 2.2 },
                    new() { AgeGroup = 50, PopulationRatio = 1.9 },
                    new() { AgeGroup = 60, PopulationRatio = 1.5 },
                    new() { AgeGroup = 70, PopulationRatio = 0.9 },
                    new() { AgeGroup = 80, PopulationRatio = 0.5 }
                },

                // 收入分布(柱状图)
                IncomeData = new List<IncomeData>
                {
                    new() { IncomeRange = "<$30k", PopulationCount = 28.5 },
                    new() { IncomeRange = "$30k-$60k", PopulationCount = 31.2 },
                    new() { IncomeRange = "$60k-$100k", PopulationCount = 22.8 },
                    new() { IncomeRange = "$100k-$150k", PopulationCount = 10.5 },
                    new() { IncomeRange = ">$150k", PopulationCount = 7.0 }
                },

                // 城市维度数据(表格)
                CityData = new List<CityStatsModel>
                {
                    new() { CityName = "New York", Population = 8804190, PerCapitaIncome = 92141.00m, Area = 783.8, GDP = 1700.0m, Region = "Northeast", RDSpending = 45.2m },
                    new() { CityName = "Los Angeles", Population = 3898747, PerCapitaIncome = 78251.00m, Area = 1213.9, GDP = 950.0m, Region = "West", RDSpending = 32.8m },
                    new() { CityName = "Chicago", Population = 2746388, PerCapitaIncome = 72189.00m, Area = 606.1, GDP = 680.0m, Region = "Midwest", RDSpending = 28.5m },
                    new() { CityName = "Houston", Population = 2304580, PerCapitaIncome = 65890.00m, Area = 1651.0, GDP = 520.0m, Region = "South", RDSpending = 21.3m },
                    new() { CityName = "Phoenix", Population = 1680992, PerCapitaIncome = 61234.00m, Area = 1338.0, GDP = 380.0m, Region = "West", RDSpending = 18.7m },
                    new() { CityName = "Philadelphia", Population = 1603797, PerCapitaIncome = 68921.00m, Area = 367.0, GDP = 410.0m, Region = "Northeast", RDSpending = 20.1m },
                    new() { CityName = "San Antonio", Population = 1434625, PerCapitaIncome = 58765.00m, Area = 1205.0, GDP = 320.0m, Region = "South", RDSpending = 15.8m },
                    new() { CityName = "San Diego", Population = 1386932, PerCapitaIncome = 79876.00m, Area = 964.0, GDP = 400.0m, Region = "West", RDSpending = 24.5m },
                    new() { CityName = "Dallas", Population = 1304379, PerCapitaIncome = 75689.00m, Area = 997.0, GDP = 480.0m, Region = "South", RDSpending = 22.9m },
                    new() { CityName = "San Jose", Population = 1013240, PerCapitaIncome = 110321.00m, Area = 469.0, GDP = 450.0m, Region = "West", RDSpending = 35.6m }
                }
            };
        }


        private CountryStatsModel GetCanadaData()
        {
            return new CountryStatsModel
            {
                CountryName = "Canada",
                Population = 38781291, // 2024年加拿大人口(模拟值)
                PerCapitaIncome = 54200.75m, // 人均收入(美元,基于加元换算)
                Area = 9984670.0, // 面积(万平方公里,世界第二)
                GDP = 2.200m, // GDP(万亿美元,2024年模拟值)
                Capital = "Ottawa", // 首都:渥太华
                LargestCity = "Toronto", // 最大城市:多伦多
                RDSpending = 1.70m, // 科研开支(GDP占比 %,加拿大研发投入占比约1.7%)

                // 人种构成(饼图)- 符合加拿大人口种族结构
                DemographicData = new List<DemographicData>
                {
                    new() { Ethnicity = "White", Percentage = 72.9 }, // 白种人(英裔/法裔为主)
                    new() { Ethnicity = "Indigenous", Percentage = 4.9 }, // 原住民
                    new() { Ethnicity = "Asian", Percentage = 16.2 }, // 亚裔(华裔、南亚裔等)
                    new() { Ethnicity = "Black", Percentage = 3.5 }, // 黑人
                    new() { Ethnicity = "Other", Percentage = 2.5 } // 其他种族
                },

                // 年龄趋势(折线图)- 加拿大老龄化略高于美国
                AgeTrendData = new List<AgeTrendData>
                {
                    new() { AgeGroup = 0, PopulationRatio = 1.1 }, // 0-9岁
                    new() { AgeGroup = 10, PopulationRatio = 1.7 }, // 10-19岁
                    new() { AgeGroup = 20, PopulationRatio = 2.0 }, // 20-29岁
                    new() { AgeGroup = 30, PopulationRatio = 2.2 }, // 30-39岁
                    new() { AgeGroup = 40, PopulationRatio = 2.1 }, // 40-49岁
                    new() { AgeGroup = 50, PopulationRatio = 2.0 }, // 50-59岁
                    new() { AgeGroup = 60, PopulationRatio = 1.6 }, // 60-69岁
                    new() { AgeGroup = 70, PopulationRatio = 1.0 }, // 70-79岁
                    new() { AgeGroup = 80, PopulationRatio = 0.6 } // 80+岁
                },

                // 收入分布(柱状图)- 以加元(CAD)为单位,符合加拿大收入水平
                IncomeData = new List<IncomeData>
                {
                    new() { IncomeRange = "<$40k CAD", PopulationCount = 29.8 }, // 低于4万加元
                    new() { IncomeRange = "$40k-$80k CAD", PopulationCount = 35.5 }, // 4-8万加元
                    new() { IncomeRange = "$80k-$120k CAD", PopulationCount = 20.2 }, // 8-12万加元
                    new() { IncomeRange = "$120k-$180k CAD", PopulationCount = 8.5 }, // 12-18万加元
                    new() { IncomeRange = ">$180k CAD", PopulationCount = 6.0 } // 高于18万加元
                },

                // 城市维度数据(表格)- 加拿大主要城市,数据均为合理模拟
                CityData = new List<CityStatsModel>
                {
                    new() { CityName = "Toronto", Population = 2794356, PerCapitaIncome = 68925.00m, Area = 630.2, GDP = 480.0m, Region = "Ontario", RDSpending = 38.5m },
                    new() { CityName = "Montreal", Population = 1762949, PerCapitaIncome = 61289.00m, Area = 365.1, GDP = 320.0m, Region = "Quebec", RDSpending = 25.8m },
                    new() { CityName = "Vancouver", Population = 662248, PerCapitaIncome = 75642.00m, Area = 115.0, GDP = 280.0m, Region = "British Columbia", RDSpending = 32.2m },
                    new() { CityName = "Calgary", Population = 1306784, PerCapitaIncome = 72158.00m, Area = 825.2, GDP = 210.0m, Region = "Alberta", RDSpending = 18.7m },
                    new() { CityName = "Edmonton", Population = 1010899, PerCapitaIncome = 67890.00m, Area = 684.4, GDP = 190.0m, Region = "Alberta", RDSpending = 16.5m },
                    new() { CityName = "Ottawa", Population = 1017449, PerCapitaIncome = 70123.00m, Area = 2778.1, GDP = 200.0m, Region = "Ontario", RDSpending = 22.3m },
                    new() { CityName = "Winnipeg", Population = 749607, PerCapitaIncome = 58765.00m, Area = 464.0, GDP = 110.0m, Region = "Manitoba", RDSpending = 9.8m },
                    new() { CityName = "Quebec City", Population = 549459, PerCapitaIncome = 59876.00m, Area = 454.0, GDP = 95.0m, Region = "Quebec", RDSpending = 8.2m },
                    new() { CityName = "Hamilton", Population = 569353, PerCapitaIncome = 57890.00m, Area = 1117.2, GDP = 85.0m, Region = "Ontario", RDSpending = 7.5m },
                    new() { CityName = "London (ON)", Population = 422324, PerCapitaIncome = 56432.00m, Area = 420.5, GDP = 70.0m, Region = "Ontario", RDSpending = 6.1m }
                }
            };
        }

        private CountryStatsModel GetAustraliaData()
        {
            return new CountryStatsModel
            {
                CountryName = "Australia",
                Population = 26759000, // 2024年澳大利亚人口(模拟值,实际约2670万)
                PerCapitaIncome = 64890.50m, // 人均收入(美元,基于澳元换算,澳元:美元≈1:0.65)
                Area = 7692024.0, // 面积(万平方公里,世界第六)
                GDP = 1.705m, // GDP(万亿美元,2024年模拟值)
                Capital = "Canberra", // 首都:堪培拉(注意:非悉尼/墨尔本)
                LargestCity = "Sydney", // 最大城市:悉尼
                RDSpending = 1.80m, // 科研开支(GDP占比 %,澳大利亚研发投入占比约1.8%)

                // 人种构成(饼图)- 符合澳大利亚多元文化人口结构
                DemographicData = new List<DemographicData>
        {
            new() { Ethnicity = "White", Percentage = 72.0 }, // 白种人(英裔为主)
            new() { Ethnicity = "Indigenous", Percentage = 3.2 }, // 原住民(土著/托雷斯海峡岛民)
            new() { Ethnicity = "Asian", Percentage = 18.8 }, // 亚裔(华裔、印度裔、菲律宾裔等)
            new() { Ethnicity = "African", Percentage = 2.5 }, // 非洲裔
            new() { Ethnicity = "Other", Percentage = 3.5 } // 其他种族(太平洋岛民等)
        },

                // 年龄趋势(折线图)- 澳大利亚老龄化程度适中,略低于加拿大
                AgeTrendData = new List<AgeTrendData>
        {
            new() { AgeGroup = 0, PopulationRatio = 1.0 }, // 0-9岁
            new() { AgeGroup = 10, PopulationRatio = 1.6 }, // 10-19岁
            new() { AgeGroup = 20, PopulationRatio = 1.9 }, // 20-29岁
            new() { AgeGroup = 30, PopulationRatio = 2.1 }, // 30-39岁
            new() { AgeGroup = 40, PopulationRatio = 2.0 }, // 40-49岁
            new() { AgeGroup = 50, PopulationRatio = 1.8 }, // 50-59岁
            new() { AgeGroup = 60, PopulationRatio = 1.4 }, // 60-69岁
            new() { AgeGroup = 70, PopulationRatio = 0.9 }, // 70-79岁
            new() { AgeGroup = 80, PopulationRatio = 0.5 } // 80+岁
        },

                // 收入分布(柱状图)- 以澳元(AUD)为单位,符合澳大利亚收入水平
                IncomeData = new List<IncomeData>
        {
            new() { IncomeRange = "<$45k AUD", PopulationCount = 28.5 }, // 低于4.5万澳元
            new() { IncomeRange = "$45k-$90k AUD", PopulationCount = 36.2 }, // 4.5-9万澳元
            new() { IncomeRange = "$90k-$150k AUD", PopulationCount = 21.5 }, // 9-15万澳元
            new() { IncomeRange = "$150k-$200k AUD", PopulationCount = 8.8 }, // 15-20万澳元
            new() { IncomeRange = ">$200k AUD", PopulationCount = 5.0 } // 高于20万澳元
        },

                // 城市维度数据(表格)- 澳大利亚主要城市,数据均为合理模拟
                CityData = new List<CityStatsModel>
        {
            new() { CityName = "Sydney", Population = 5367206, PerCapitaIncome = 78950.00m, Area = 12368.2, GDP = 380.0m, Region = "New South Wales", RDSpending = 42.8m },
            new() { CityName = "Melbourne", Population = 5159211, PerCapitaIncome = 76820.00m, Area = 9992.5, GDP = 350.0m, Region = "Victoria", RDSpending = 39.5m },
            new() { CityName = "Brisbane", Population = 2628020, PerCapitaIncome = 70150.00m, Area = 15826.0, GDP = 180.0m, Region = "Queensland", RDSpending = 21.3m },
            new() { CityName = "Perth", Population = 2125110, PerCapitaIncome = 73280.00m, Area = 6417.9, GDP = 160.0m, Region = "Western Australia", RDSpending = 18.7m },
            new() { CityName = "Adelaide", Population = 1304637, PerCapitaIncome = 68920.00m, Area = 3257.0, GDP = 95.0m, Region = "South Australia", RDSpending = 12.5m },
            new() { CityName = "Canberra", Population = 452670, PerCapitaIncome = 82560.00m, Area = 814.2, GDP = 85.0m, Region = "Australian Capital Territory", RDSpending = 15.8m },
            new() { CityName = "Gold Coast", Population = 678020, PerCapitaIncome = 65890.00m, Area = 1402.0, GDP = 70.0m, Region = "Queensland", RDSpending = 8.2m },
            new() { CityName = "Newcastle", Population = 322278, PerCapitaIncome = 62150.00m, Area = 1172.0, GDP = 45.0m, Region = "New South Wales", RDSpending = 6.5m },
            new() { CityName = "Sunshine Coast", Population = 346520, PerCapitaIncome = 64780.00m, Area = 3068.0, GDP = 40.0m, Region = "Queensland", RDSpending = 5.8m },
            new() { CityName = "Hobart", Population = 247321, PerCapitaIncome = 61890.00m, Area = 1357.0, GDP = 35.0m, Region = "Tasmania", RDSpending = 4.2m }
        }
            };
        }

        private CountryStatsModel GetUKData()
        {
            return new CountryStatsModel
            {
                CountryName = "UK",
                Population = 67530172, // 2024年英国人口(模拟值,实际约6750万)
                PerCapitaIncome = 48520.80m, // 人均收入(美元,基于英镑换算,GBP:USD≈1:1.27)
                Area = 242495.0, // 面积(平方公里,含英格兰、苏格兰、威尔士、北爱尔兰)
                GDP = 3.150m, // GDP(万亿美元,2024年模拟值)
                Capital = "London", // 首都:伦敦(英国唯一的国际化大都市)
                LargestCity = "London", // 最大城市:伦敦(英国城市规模高度集中)
                RDSpending = 1.75m, // 科研开支(GDP占比 %,英国研发投入占比约1.75%)

                // 人种构成(饼图)- 符合英国多元文化人口结构(2024年模拟)
                DemographicData = new List<DemographicData>
                {
                    new() { Ethnicity = "White", Percentage = 81.0 }, // 白种人(英格兰裔、苏格兰裔、威尔士裔等)
                    new() { Ethnicity = "Asian", Percentage = 9.6 }, // 亚裔(印度裔、巴基斯坦裔、孟加拉裔、华裔等)
                    new() { Ethnicity = "Black", Percentage = 4.2 }, // 黑人(加勒比裔、非洲裔)
                    new() { Ethnicity = "Mixed", Percentage = 3.0 }, // 混血人种
                    new() { Ethnicity = "Other", Percentage = 2.2 } // 其他种族(中东裔、东欧裔等)
                },

                // 年龄趋势(折线图)- 英国老龄化程度高于美/加/澳,低于日本
                AgeTrendData = new List<AgeTrendData>
                {
                    new() { AgeGroup = 0, PopulationRatio = 1.0 }, // 0-9岁
                    new() { AgeGroup = 10, PopulationRatio = 1.5 }, // 10-19岁
                    new() { AgeGroup = 20, PopulationRatio = 1.8 }, // 20-29岁
                    new() { AgeGroup = 30, PopulationRatio = 2.0 }, // 30-39岁
                    new() { AgeGroup = 40, PopulationRatio = 2.0 }, // 40-49岁
                    new() { AgeGroup = 50, PopulationRatio = 1.9 }, // 50-59岁
                    new() { AgeGroup = 60, PopulationRatio = 1.7 }, // 60-69岁
                    new() { AgeGroup = 70, PopulationRatio = 1.1 }, // 70-79岁
                    new() { AgeGroup = 80, PopulationRatio = 0.6 } // 80+岁
                },

                // 收入分布(柱状图)- 以英镑(GBP)为单位,符合英国收入水平
                IncomeData = new List<IncomeData>
                {
                    new() { IncomeRange = "<£30k GBP", PopulationCount = 31.2 }, // 低于3万英镑
                    new() { IncomeRange = "£30k-£60k GBP", PopulationCount = 38.5 }, // 3-6万英镑
                    new() { IncomeRange = "£60k-£100k GBP", PopulationCount = 18.8 }, // 6-10万英镑
                    new() { IncomeRange = "£100k-£150k GBP", PopulationCount = 7.5 }, // 10-15万英镑
                    new() { IncomeRange = ">£150k GBP", PopulationCount = 4.0 } // 高于15万英镑
                },

                // 城市维度数据(表格)- 英国主要城市,覆盖英格兰/苏格兰/威尔士,数据合理模拟
                CityData = new List<CityStatsModel>
                {
                    new() { CityName = "London", Population = 9787426, PerCapitaIncome = 65890.00m, Area = 1572.0, GDP = 520.0m, Region = "England", RDSpending = 58.5m },
                    new() { CityName = "Birmingham", Population = 1144919, PerCapitaIncome = 42150.00m, Area = 267.0, GDP = 85.0m, Region = "England (West Midlands)", RDSpending = 9.2m },
                    new() { CityName = "Manchester", Population = 552000, PerCapitaIncome = 45870.00m, Area = 115.0, GDP = 78.0m, Region = "England (North West)", RDSpending = 10.5m },
                    new() { CityName = "Leeds", Population = 812000, PerCapitaIncome = 41230.00m, Area = 551.0, GDP = 65.0m, Region = "England (Yorkshire)", RDSpending = 7.8m },
                    new() { CityName = "Glasgow", Population = 632350, PerCapitaIncome = 38920.00m, Area = 175.0, GDP = 52.0m, Region = "Scotland", RDSpending = 6.5m },
                    new() { CityName = "Liverpool", Population = 494814, PerCapitaIncome = 39870.00m, Area = 111.0, GDP = 48.0m, Region = "England (North West)", RDSpending = 5.8m },
                    new() { CityName = "Newcastle", Population = 308200, PerCapitaIncome = 38760.00m, Area = 113.0, GDP = 32.0m, Region = "England (North East)", RDSpending = 4.1m },
                    new() { CityName = "Sheffield", Population = 556500, PerCapitaIncome = 40120.00m, Area = 367.0, GDP = 45.0m, Region = "England (Yorkshire)", RDSpending = 5.2m },
                    new() { CityName = "Bristol", Population = 472400, PerCapitaIncome = 48950.00m, Area = 110.0, GDP = 42.0m, Region = "England (South West)", RDSpending = 6.8m },
                    new() { CityName = "Edinburgh", Population = 526470, PerCapitaIncome = 46890.00m, Area = 264.0, GDP = 55.0m, Region = "Scotland", RDSpending = 7.5m }
                }
            };
        }

        private CountryStatsModel GetHomeData() => new() { /* 首页汇总数据 */ };
        #endregion
    }
}


using LiveCharts;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Shared.Models
{
    public class AgeTrendData
    {
        public int AgeGroup { get; set; } // 年龄组(如10,20,30...)
        public double PopulationRatio { get; set; } // 该年龄组占比
        public ChartValues<double> TrendValues => new() { PopulationRatio };
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Shared.Models
{
    /// <summary>
    /// 城市级统计数据
    /// </summary>
    public class CityStatsModel
    {
        public string CityName { get; set; } = string.Empty;
        public long Population { get; set; }
        public decimal PerCapitaIncome { get; set; }
        public double Area { get; set; }
        public decimal GDP { get; set; } // 城市GDP(亿美元)
        public string Region { get; set; } = string.Empty; // 所属区域
        public decimal RDSpending { get; set; } // 科研开支(亿美金)
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Shared.Models
{
    /// <summary>
    /// 国家级统计数据
    /// </summary>
    public class CountryStatsModel
    {
        public string CountryName { get; set; } = string.Empty;
        public long Population { get; set; } // 人口
        public decimal PerCapitaIncome { get; set; } // 人均收入(美元)
        public double Area { get; set; } // 面积(万平方公里)
        public decimal GDP { get; set; } // GDP(万亿美元)
        public string Capital { get; set; } = string.Empty; // 首都
        public string LargestCity { get; set; } = string.Empty; // 最大城市
        public decimal RDSpending { get; set; } // 科研开支(GDP占比 %)

        // 图表数据
        public List<DemographicData> DemographicData { get; set; } = new(); // 人种构成
        public List<AgeTrendData> AgeTrendData { get; set; } = new(); // 年龄趋势
        public List<IncomeData> IncomeData { get; set; } = new(); // 收入分布
                                                                  // 城市维度数据
        public List<CityStatsModel> CityData { get; set; } = new(); // 城市数据
    }
}


using LiveCharts;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Shared.Models
{
    public class DemographicData
    {
        public string Ethnicity { get; set; } = string.Empty; // 人种
        public double Percentage { get; set; } // 占比
        public SeriesCollection PieSeries => new()
        {
            new LiveCharts.Wpf.PieSeries
            {
                Title = Ethnicity,
                Values = new ChartValues<double> { Percentage },
                DataLabels = true
            }
        };
    }
}


using LiveCharts;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Shared.Models
{
    public class IncomeData
    {
        public string IncomeRange { get; set; } = string.Empty; // 收入区间
        public double PopulationCount { get; set; } // 该区间人口数(百万)
        public ChartValues<double> ColumnValues => new() { PopulationCount };
    }
}

 

//AustraliaModule
using Prism.Ioc;
using Prism.Modularity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AustraliaModule
{
    public class AustraliaModule : IModule
    {
        public void OnInitialized(IContainerProvider containerProvider)
        {

        }

        public void RegisterTypes(IContainerRegistry containerRegistry)
        {
            containerRegistry.RegisterForNavigation<AustraliaView>();
        }
    }
}
<UserControl x:Class="AustraliaModule.AustraliaView"
             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:AustraliaModule"
                          xmlns:prism="http://prismlibrary.com/"
             xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
             xmlns:shared="clr-namespace:Shared.Models;assembly=Shared"
             prism:ViewModelLocator.AutoWireViewModel="True">
    <UserControl.Resources>
        <!-- 转换器:布尔值转可见性 -->
        <BooleanToVisibilityConverter x:Key="BoolToVis"/>
    </UserControl.Resources>

    <Grid Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <!-- 1. 页面标题 -->
        <TextBlock Grid.Row="0" Text="{Binding CountryData.CountryName}" 
                 FontSize="20" FontWeight="Bold" Margin="0 0 0 10"/>

        <!-- 2. 图表区域(饼图+折线图+柱状图) -->
        <Grid Grid.Row="1" Margin="0 10 0 10">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="1*"/>
                <ColumnDefinition Width="1*"/>
                <ColumnDefinition Width="1*"/>
            </Grid.ColumnDefinitions>

            <!-- 人种构成饼图 -->
            <Grid Grid.Column="0" Margin="0 0 10 0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <TextBlock Text="人种构成" FontSize="14" FontWeight="SemiBold" Margin="0 0 0 5"/>
                <lvc:PieChart Grid.Row="1" Series="{Binding DemographicSeries}" 
                            LegendLocation="Bottom"/>
            </Grid>

            <!-- 年龄趋势折线图 -->
            <Grid Grid.Column="1" Margin="5 0 5 0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <TextBlock Text="年龄分布趋势" FontSize="14" FontWeight="SemiBold" Margin="0 0 0 5"/>
                <lvc:CartesianChart Grid.Row="1" Series="{Binding AgeTrendSeries}">
                    <lvc:CartesianChart.AxisX>
                        <lvc:Axis Title="年龄组" Labels="{Binding AgeGroupLabels}"/>
                    </lvc:CartesianChart.AxisX>
                    <lvc:CartesianChart.AxisY>
                        <lvc:Axis Title="人口占比(%)"/>
                    </lvc:CartesianChart.AxisY>
                </lvc:CartesianChart>
            </Grid>

            <!-- 收入分布柱状图 -->
            <Grid Grid.Column="2" Margin="10 0 0 0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <TextBlock Text="收入分布" FontSize="14" FontWeight="SemiBold" Margin="0 0 0 5"/>
                <lvc:CartesianChart Grid.Row="1" Series="{Binding IncomeSeries}">
                    <lvc:CartesianChart.AxisX>
                        <lvc:Axis Title="收入区间(USD)" Labels="{Binding IncomeRangeLabels}"/>
                    </lvc:CartesianChart.AxisX>
                    <lvc:CartesianChart.AxisY>
                        <lvc:Axis Title="人口数(百万)"/>
                    </lvc:CartesianChart.AxisY>
                </lvc:CartesianChart>
            </Grid>
        </Grid>

        <DataGrid Grid.Row="3" ItemsSource="{Binding PagedCityData}" AutoGenerateColumns="False"
                CanUserAddRows="False" CanUserDeleteRows="False"
                FontSize="30">
            <DataGrid.Resources>
                <Style TargetType="{x:Type DataGridTextColumn}">
                    <Setter Property="Width" Value="*"/>
                </Style>
            </DataGrid.Resources>
            <DataGrid.Columns>
                <DataGridTextColumn Header="城市名" Binding="{Binding CityName}" 
                                  Visibility="{Binding ShowCityName, Converter={StaticResource BoolToVis}}"/>
                <DataGridTextColumn Header="人口" Binding="{Binding Population, StringFormat=N0}" 
                                  Visibility="{Binding ShowPopulation, Converter={StaticResource BoolToVis}}"/>
                <DataGridTextColumn Header="人均收入(USD)" Binding="{Binding PerCapitaIncome, StringFormat=C2}" 
                                  Visibility="{Binding ShowPerCapitaIncome, Converter={StaticResource BoolToVis}}"/>
                <DataGridTextColumn Header="面积(km²)" Binding="{Binding Area, StringFormat=N1}" 
                                  Visibility="{Binding ShowArea, Converter={StaticResource BoolToVis}}"/>
                <DataGridTextColumn Header="GDP(亿美元)" Binding="{Binding GDP, StringFormat=N1}" 
                                  Visibility="{Binding ShowGDP, Converter={StaticResource BoolToVis}}"/>
                <DataGridTextColumn Header="科研开支(亿USD)" Binding="{Binding RDSpending, StringFormat=N1}" 
                                  Visibility="{Binding ShowRDSpending, Converter={StaticResource BoolToVis}}"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</UserControl>

using LiveCharts;
using LiveCharts.Wpf;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Regions;
using Shared.Models;
using Shared.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace AustraliaModule
{
    public class AustraliaViewModel : BindableBase, INavigationAware
    {
        #region 依赖注入&核心字段
        private readonly MockDataService _mockDataService;
        private CountryStatsModel _countryData = new();
        private List<CityStatsModel> _allCityData = new();
        private List<CityStatsModel> _pagedCityData = new();

        // 分页参数
        private int _currentPage = 1;
        private int _pageSize = 5;
        private int _totalPages;

        // 列显隐控制
        private bool _showCityName = true;
        private bool _showPopulation = true;
        private bool _showPerCapitaIncome = true;
        private bool _showArea = true;
        private bool _showGDP = true;
        private bool _showRDSpending = true;

        // 图表数据
        private SeriesCollection _demographicSeries = new();
        private SeriesCollection _ageTrendSeries = new();
        private SeriesCollection _incomeSeries = new();
        private List<string> _ageGroupLabels = new();
        private List<string> _incomeRangeLabels = new();
        #endregion

        #region 绑定属性
        public CountryStatsModel CountryData
        {
            get => _countryData;
            set => SetProperty(ref _countryData, value);
        }

        public List<CityStatsModel> PagedCityData
        {
            get => _pagedCityData;
            set => SetProperty(ref _pagedCityData, value);
        }

        // 分页属性
        public int CurrentPage
        {
            get => _currentPage;
            set
            {
                if (SetProperty(ref _currentPage, value))
                {
                    UpdatePagedData();
                    RaisePropertyChanged(nameof(CanGoPrevious));
                    RaisePropertyChanged(nameof(CanGoNext));
                }
            }
        }

        public int TotalPages
        {
            get => _totalPages;
            set => SetProperty(ref _totalPages, value);
        }

        public bool CanGoPrevious => CurrentPage > 1;
        public bool CanGoNext => CurrentPage < TotalPages;

        // 列显隐属性
        public bool ShowCityName
        {
            get => _showCityName;
            set => SetProperty(ref _showCityName, value);
        }

        public bool ShowPopulation
        {
            get => _showPopulation;
            set => SetProperty(ref _showPopulation, value);
        }

        public bool ShowPerCapitaIncome
        {
            get => _showPerCapitaIncome;
            set => SetProperty(ref _showPerCapitaIncome, value);
        }

        public bool ShowArea
        {
            get => _showArea;
            set => SetProperty(ref _showArea, value);
        }

        public bool ShowGDP
        {
            get => _showGDP;
            set => SetProperty(ref _showGDP, value);
        }

        public bool ShowRDSpending
        {
            get => _showRDSpending;
            set => SetProperty(ref _showRDSpending, value);
        }

        // 图表绑定属性
        public SeriesCollection DemographicSeries
        {
            get => _demographicSeries;
            set => SetProperty(ref _demographicSeries, value);
        }

        public SeriesCollection AgeTrendSeries
        {
            get => _ageTrendSeries;
            set => SetProperty(ref _ageTrendSeries, value);
        }

        public SeriesCollection IncomeSeries
        {
            get => _incomeSeries;
            set => SetProperty(ref _incomeSeries, value);
        }

        public List<string> AgeGroupLabels
        {
            get => _ageGroupLabels;
            set => SetProperty(ref _ageGroupLabels, value);
        }

        public List<string> IncomeRangeLabels
        {
            get => _incomeRangeLabels;
            set => SetProperty(ref _incomeRangeLabels, value);
        }

        // 分页命令
        public ICommand PreviousPageCommand => new DelegateCommand(() => CurrentPage--);
        public ICommand NextPageCommand => new DelegateCommand(() => CurrentPage++);
        #endregion

        public AustraliaViewModel(MockDataService mockDataService)
        {
            _mockDataService = mockDataService;
        }

        #region 导航&数据加载
        public void OnNavigatedTo(NavigationContext navigationContext)
        {
            CountryData = _mockDataService.GetCountryData("Australia");
            _allCityData = CountryData.CityData;
            PagedCityData = _allCityData.Take(10).ToList();
            // 初始化分页
            TotalPages = (int)Math.Ceiling((double)_allCityData.Count / _pageSize);
            CurrentPage = 1;

            // 初始化图表
            InitCharts();
        }

        public bool IsNavigationTarget(NavigationContext navigationContext) => true;
        public void OnNavigatedFrom(NavigationContext navigationContext) { }
        #endregion

        #region 私有方法
        // 初始化图表数据
        private void InitCharts()
        {
            // 1. 人种构成饼图
            DemographicSeries = new SeriesCollection();
            foreach (var item in CountryData.DemographicData)
            {
                DemographicSeries.Add(new PieSeries
                {
                    Title = item.Ethnicity,
                    Values = new ChartValues<double> { item.Percentage },
                    DataLabels = true
                });
            }

            // 2. 年龄趋势折线图
            AgeTrendSeries = new SeriesCollection
            {
                new LineSeries
                {
                    Title = "年龄占比",
                    Values = new ChartValues<double>(CountryData.AgeTrendData.Select(x => x.PopulationRatio)),
                    LineSmoothness = 1, // 平滑曲线
                    PointGeometry = DefaultGeometries.Circle,
                    PointGeometrySize = 5
                }
            };
            AgeGroupLabels = CountryData.AgeTrendData.Select(x => x.AgeGroup.ToString()).ToList();

            // 3. 收入分布柱状图
            IncomeSeries = new SeriesCollection
            {
                new ColumnSeries
                {
                    Title= "人口数",
                    Values= new ChartValues<double>(CountryData.IncomeData.Select(x => x.PopulationCount))
                }
            };
            IncomeRangeLabels = CountryData.IncomeData.Select(x => x.IncomeRange).ToList();
        }

        // 更新分页数据
        private void UpdatePagedData()
        {
            PagedCityData = _allCityData
                .Skip((CurrentPage - 1) * _pageSize)
                .Take(_pageSize)
                .ToList();
        }

        #endregion
    }
}

 

 

 

//CanadaModule
using Prism.Ioc;
using Prism.Modularity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CanadaModule
{
    public class CanadaModule : IModule
    {
        public void OnInitialized(IContainerProvider containerProvider)
        {

        }

        public void RegisterTypes(IContainerRegistry containerRegistry)
        {
            containerRegistry.RegisterForNavigation<CanadaView>();
        }
    }
}


<UserControl x:Class="CanadaModule.CanadaView"
             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:CanadaModule"
             xmlns:prism="http://prismlibrary.com/"
             xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
             xmlns:shared="clr-namespace:Shared.Models;assembly=Shared"
             prism:ViewModelLocator.AutoWireViewModel="True">
    <UserControl.Resources>
        <!-- 转换器:布尔值转可见性 -->
        <BooleanToVisibilityConverter x:Key="BoolToVis"/>
    </UserControl.Resources>

    <Grid Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <!-- 1. 页面标题 -->
        <TextBlock Grid.Row="0" Text="{Binding CountryData.CountryName}" 
                 FontSize="20" FontWeight="Bold" Margin="0 0 0 10"/>

        <!-- 2. 图表区域(饼图+折线图+柱状图) -->
        <Grid Grid.Row="1" Margin="0 10 0 10">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="1*"/>
                <ColumnDefinition Width="1*"/>
                <ColumnDefinition Width="1*"/>
            </Grid.ColumnDefinitions>

            <!-- 人种构成饼图 -->
            <Grid Grid.Column="0" Margin="0 0 10 0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <TextBlock Text="人种构成" FontSize="14" FontWeight="SemiBold" Margin="0 0 0 5"/>
                <lvc:PieChart Grid.Row="1" Series="{Binding DemographicSeries}" 
                            LegendLocation="Bottom"/>
            </Grid>

            <!-- 年龄趋势折线图 -->
            <Grid Grid.Column="1" Margin="5 0 5 0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <TextBlock Text="年龄分布趋势" FontSize="14" FontWeight="SemiBold" Margin="0 0 0 5"/>
                <lvc:CartesianChart Grid.Row="1" Series="{Binding AgeTrendSeries}">
                    <lvc:CartesianChart.AxisX>
                        <lvc:Axis Title="年龄组" Labels="{Binding AgeGroupLabels}"/>
                    </lvc:CartesianChart.AxisX>
                    <lvc:CartesianChart.AxisY>
                        <lvc:Axis Title="人口占比(%)"/>
                    </lvc:CartesianChart.AxisY>
                </lvc:CartesianChart>
            </Grid>

            <!-- 收入分布柱状图 -->
            <Grid Grid.Column="2" Margin="10 0 0 0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <TextBlock Text="收入分布" FontSize="14" FontWeight="SemiBold" Margin="0 0 0 5"/>
                <lvc:CartesianChart Grid.Row="1" Series="{Binding IncomeSeries}">
                    <lvc:CartesianChart.AxisX>
                        <lvc:Axis Title="收入区间(USD)" Labels="{Binding IncomeRangeLabels}"/>
                    </lvc:CartesianChart.AxisX>
                    <lvc:CartesianChart.AxisY>
                        <lvc:Axis Title="人口数(百万)"/>
                    </lvc:CartesianChart.AxisY>
                </lvc:CartesianChart>
            </Grid>
        </Grid>

        <DataGrid Grid.Row="3" ItemsSource="{Binding PagedCityData}" AutoGenerateColumns="False"
                CanUserAddRows="False" CanUserDeleteRows="False"
                FontSize="30">
            <DataGrid.Resources>
                <Style TargetType="{x:Type DataGridTextColumn}">
                    <Setter Property="Width" Value="*"/>
                </Style>
            </DataGrid.Resources>
            <DataGrid.Columns>
                <DataGridTextColumn Header="城市名" Binding="{Binding CityName}" 
                                  Visibility="{Binding ShowCityName, Converter={StaticResource BoolToVis}}"/>
                <DataGridTextColumn Header="人口" Binding="{Binding Population, StringFormat=N0}" 
                                  Visibility="{Binding ShowPopulation, Converter={StaticResource BoolToVis}}"/>
                <DataGridTextColumn Header="人均收入(USD)" Binding="{Binding PerCapitaIncome, StringFormat=C2}" 
                                  Visibility="{Binding ShowPerCapitaIncome, Converter={StaticResource BoolToVis}}"/>
                <DataGridTextColumn Header="面积(km²)" Binding="{Binding Area, StringFormat=N1}" 
                                  Visibility="{Binding ShowArea, Converter={StaticResource BoolToVis}}"/>
                <DataGridTextColumn Header="GDP(亿美元)" Binding="{Binding GDP, StringFormat=N1}" 
                                  Visibility="{Binding ShowGDP, Converter={StaticResource BoolToVis}}"/>
                <DataGridTextColumn Header="科研开支(亿USD)" Binding="{Binding RDSpending, StringFormat=N1}" 
                                  Visibility="{Binding ShowRDSpending, Converter={StaticResource BoolToVis}}"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</UserControl>

using LiveCharts;
using LiveCharts.Wpf;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Regions;
using Shared.Models;
using Shared.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace CanadaModule
{
    public class CanadaViewModel : BindableBase, INavigationAware
    {
        #region 依赖注入&核心字段
        private readonly MockDataService _mockDataService;
        private CountryStatsModel _countryData = new();
        private List<CityStatsModel> _allCityData = new();
        private List<CityStatsModel> _pagedCityData = new();

        // 分页参数
        private int _currentPage = 1;
        private int _pageSize = 5;
        private int _totalPages;

        // 列显隐控制
        private bool _showCityName = true;
        private bool _showPopulation = true;
        private bool _showPerCapitaIncome = true;
        private bool _showArea = true;
        private bool _showGDP = true;
        private bool _showRDSpending = true;

        // 图表数据
        private SeriesCollection _demographicSeries = new();
        private SeriesCollection _ageTrendSeries = new();
        private SeriesCollection _incomeSeries = new();
        private List<string> _ageGroupLabels = new();
        private List<string> _incomeRangeLabels = new();
        #endregion

        #region 绑定属性
        public CountryStatsModel CountryData
        {
            get => _countryData;
            set => SetProperty(ref _countryData, value);
        }

        public List<CityStatsModel> PagedCityData
        {
            get => _pagedCityData;
            set => SetProperty(ref _pagedCityData, value);
        }

        // 分页属性
        public int CurrentPage
        {
            get => _currentPage;
            set
            {
                if (SetProperty(ref _currentPage, value))
                {
                    UpdatePagedData();
                    RaisePropertyChanged(nameof(CanGoPrevious));
                    RaisePropertyChanged(nameof(CanGoNext));
                }
            }
        }

        public int TotalPages
        {
            get => _totalPages;
            set => SetProperty(ref _totalPages, value);
        }

        public bool CanGoPrevious => CurrentPage > 1;
        public bool CanGoNext => CurrentPage < TotalPages;

        // 列显隐属性
        public bool ShowCityName
        {
            get => _showCityName;
            set => SetProperty(ref _showCityName, value);
        }

        public bool ShowPopulation
        {
            get => _showPopulation;
            set => SetProperty(ref _showPopulation, value);
        }

        public bool ShowPerCapitaIncome
        {
            get => _showPerCapitaIncome;
            set => SetProperty(ref _showPerCapitaIncome, value);
        }

        public bool ShowArea
        {
            get => _showArea;
            set => SetProperty(ref _showArea, value);
        }

        public bool ShowGDP
        {
            get => _showGDP;
            set => SetProperty(ref _showGDP, value);
        }

        public bool ShowRDSpending
        {
            get => _showRDSpending;
            set => SetProperty(ref _showRDSpending, value);
        }

        // 图表绑定属性
        public SeriesCollection DemographicSeries
        {
            get => _demographicSeries;
            set => SetProperty(ref _demographicSeries, value);
        }

        public SeriesCollection AgeTrendSeries
        {
            get => _ageTrendSeries;
            set => SetProperty(ref _ageTrendSeries, value);
        }

        public SeriesCollection IncomeSeries
        {
            get => _incomeSeries;
            set => SetProperty(ref _incomeSeries, value);
        }

        public List<string> AgeGroupLabels
        {
            get => _ageGroupLabels;
            set => SetProperty(ref _ageGroupLabels, value);
        }

        public List<string> IncomeRangeLabels
        {
            get => _incomeRangeLabels;
            set => SetProperty(ref _incomeRangeLabels, value);
        }

        // 分页命令
        public ICommand PreviousPageCommand => new DelegateCommand(() => CurrentPage--);
        public ICommand NextPageCommand => new DelegateCommand(() => CurrentPage++);
        #endregion

        public CanadaViewModel(MockDataService mockDataService)
        {
            _mockDataService = mockDataService;
        }

        #region 导航&数据加载
        public void OnNavigatedTo(NavigationContext navigationContext)
        {
            CountryData = _mockDataService.GetCountryData("Canada");
            _allCityData = CountryData.CityData;
            PagedCityData = _allCityData.Take(10).ToList();
            // 初始化分页
            TotalPages = (int)Math.Ceiling((double)_allCityData.Count / _pageSize);
            CurrentPage = 1;

            // 初始化图表
            InitCharts();
        }

        public bool IsNavigationTarget(NavigationContext navigationContext) => true;
        public void OnNavigatedFrom(NavigationContext navigationContext) { }
        #endregion

        #region 私有方法
        // 初始化图表数据
        private void InitCharts()
        {
            // 1. 人种构成饼图
            DemographicSeries = new SeriesCollection();
            foreach (var item in CountryData.DemographicData)
            {
                DemographicSeries.Add(new PieSeries
                {
                    Title = item.Ethnicity,
                    Values = new ChartValues<double> { item.Percentage },
                    DataLabels = true
                });
            }

            // 2. 年龄趋势折线图
            AgeTrendSeries = new SeriesCollection
            {
                new LineSeries
                {
                    Title = "年龄占比",
                    Values = new ChartValues<double>(CountryData.AgeTrendData.Select(x => x.PopulationRatio)),
                    LineSmoothness = 1, // 平滑曲线
                    PointGeometry = DefaultGeometries.Circle,
                    PointGeometrySize = 5
                }
            };
            AgeGroupLabels = CountryData.AgeTrendData.Select(x => x.AgeGroup.ToString()).ToList();

            // 3. 收入分布柱状图
            IncomeSeries = new SeriesCollection
            {
                new ColumnSeries
                {
                    Title= "人口数",
                    Values= new ChartValues<double>(CountryData.IncomeData.Select(x => x.PopulationCount))
                }
            };
            IncomeRangeLabels = CountryData.IncomeData.Select(x => x.IncomeRange).ToList();
        }

        // 更新分页数据
        private void UpdatePagedData()
        {
            PagedCityData = _allCityData
                .Skip((CurrentPage - 1) * _pageSize)
                .Take(_pageSize)
                .ToList();
        }

        #endregion
    }
}

 

 

 

//HomeModule
using Prism.Ioc;
using Prism.Modularity;
using Prism.Regions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HomeModule
{
    public class HomeModule : IModule
    {
        public void OnInitialized(IContainerProvider containerProvider)
        {
            var regionManager = containerProvider.Resolve<IRegionManager>();
            regionManager.RequestNavigate("ContentRegion", "HomeView");
        }

        public void RegisterTypes(IContainerRegistry containerRegistry)
        {
            containerRegistry.RegisterForNavigation<HomeView>();
        }
    }
}

<UserControl x:Class="HomeModule.HomeView"
             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:HomeModule"
             xmlns:prism="http://prismlibrary.com/"
             xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
             prism:ViewModelLocator.AutoWireViewModel="True"
             mc:Ignorable="d" 
             d:DesignHeight="800" d:DesignWidth="1200">
    <Grid Margin="10">
        <!-- 整体布局:4行,每行对应一个国家 -->
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Grid.Resources>
            <!-- 通用样式:行标题 -->
            <Style x:Key="RowTitleStyle" TargetType="TextBlock">
                <Setter Property="FontSize" Value="16"/>
                <Setter Property="FontWeight" Value="Bold"/>
                <Setter Property="Margin" Value="0 0 0 10"/>
                <Setter Property="VerticalAlignment" Value="Top"/>
            </Style>
            <!-- 通用样式:图表容器 -->
            <Style x:Key="ChartContainerStyle" TargetType="Grid">
                <Setter Property="Margin" Value="5"/>
            </Style>
            <!-- 通用样式:图表标题 -->
            <Style x:Key="ChartTitleStyle" TargetType="TextBlock">
                <Setter Property="FontSize" Value="12"/>
                <Setter Property="FontWeight" Value="SemiBold"/>
                <Setter Property="Margin" Value="0 0 0 5"/>
                <Setter Property="HorizontalAlignment" Value="Center"/>
            </Style>
        </Grid.Resources>

        <!-- 第一行:美国数据 -->
        <Grid Grid.Row="0" Margin="0 0 0 10">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="150"/>
                <ColumnDefinition Width="1*"/>
                <ColumnDefinition Width="1*"/>
                <ColumnDefinition Width="1*"/>
            </Grid.ColumnDefinitions>
            <!-- 行标题 -->
            <TextBlock Grid.Column="0" Text="美国 (USA)" Style="{StaticResource RowTitleStyle}"/>
            <!-- 人口饼图 -->
            <Grid Grid.Column="1" Style="{StaticResource ChartContainerStyle}">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <TextBlock Grid.Row="0" Text="人种构成" Style="{StaticResource ChartTitleStyle}"/>
                <lvc:PieChart Grid.Row="1" Series="{Binding USADemographicSeries}" 
                              LegendLocation="Bottom" Height="150"/>
            </Grid>
            <!-- 年龄趋势图 -->
            <Grid Grid.Column="2" Style="{StaticResource ChartContainerStyle}">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <TextBlock Grid.Row="0" Text="年龄分布趋势" Style="{StaticResource ChartTitleStyle}"/>
                <lvc:CartesianChart Grid.Row="1" Series="{Binding USAAgeTrendSeries}" Height="150">
                    <lvc:CartesianChart.AxisX>
                        <lvc:Axis Labels="{Binding USAAgeGroupLabels}"/>
                    </lvc:CartesianChart.AxisX>
                    <lvc:CartesianChart.AxisY>
                        <lvc:Axis Title="占比(%)"/>
                    </lvc:CartesianChart.AxisY>
                </lvc:CartesianChart>
            </Grid>
            <!-- 收入柱状图 -->
            <Grid Grid.Column="3" Style="{StaticResource ChartContainerStyle}">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <TextBlock Grid.Row="0" Text="收入分布" Style="{StaticResource ChartTitleStyle}"/>
                <lvc:CartesianChart Grid.Row="1" Series="{Binding USAIncomeSeries}" Height="150">
                    <lvc:CartesianChart.AxisX>
                        <lvc:Axis Labels="{Binding USAIncomeRangeLabels}"/>
                    </lvc:CartesianChart.AxisX>
                    <lvc:CartesianChart.AxisY>
                        <lvc:Axis Title="人口(百万)"/>
                    </lvc:CartesianChart.AxisY>
                </lvc:CartesianChart>
            </Grid>
        </Grid>

        <!-- 第二行:加拿大数据 -->
        <Grid Grid.Row="1" Margin="0 10 0 10">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="150"/>
                <ColumnDefinition Width="1*"/>
                <ColumnDefinition Width="1*"/>
                <ColumnDefinition Width="1*"/>
            </Grid.ColumnDefinitions>
            <!-- 行标题 -->
            <TextBlock Grid.Column="0" Text="加拿大 (Canada)" Style="{StaticResource RowTitleStyle}"/>
            <!-- 人口饼图 -->
            <Grid Grid.Column="1" Style="{StaticResource ChartContainerStyle}">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <TextBlock Grid.Row="0" Text="人种构成" Style="{StaticResource ChartTitleStyle}"/>
                <lvc:PieChart Grid.Row="1" Series="{Binding CanadaDemographicSeries}" 
                              LegendLocation="Bottom" Height="150"/>
            </Grid>
            <!-- 年龄趋势图 -->
            <Grid Grid.Column="2" Style="{StaticResource ChartContainerStyle}">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <TextBlock Grid.Row="0" Text="年龄分布趋势" Style="{StaticResource ChartTitleStyle}"/>
                <lvc:CartesianChart Grid.Row="1" Series="{Binding CanadaAgeTrendSeries}" Height="150">
                    <lvc:CartesianChart.AxisX>
                        <lvc:Axis Labels="{Binding CanadaAgeGroupLabels}"/>
                    </lvc:CartesianChart.AxisX>
                    <lvc:CartesianChart.AxisY>
                        <lvc:Axis Title="占比(%)"/>
                    </lvc:CartesianChart.AxisY>
                </lvc:CartesianChart>
            </Grid>
            <!-- 收入柱状图 -->
            <Grid Grid.Column="3" Style="{StaticResource ChartContainerStyle}">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <TextBlock Grid.Row="0" Text="收入分布" Style="{StaticResource ChartTitleStyle}"/>
                <lvc:CartesianChart Grid.Row="1" Series="{Binding CanadaIncomeSeries}" Height="150">
                    <lvc:CartesianChart.AxisX>
                        <lvc:Axis Labels="{Binding CanadaIncomeRangeLabels}"/>
                    </lvc:CartesianChart.AxisX>
                    <lvc:CartesianChart.AxisY>
                        <lvc:Axis Title="人口(百万)"/>
                    </lvc:CartesianChart.AxisY>
                </lvc:CartesianChart>
            </Grid>
        </Grid>

        <!-- 第三行:澳大利亚数据 -->
        <Grid Grid.Row="2" Margin="0 10 0 10">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="150"/>
                <ColumnDefinition Width="1*"/>
                <ColumnDefinition Width="1*"/>
                <ColumnDefinition Width="1*"/>
            </Grid.ColumnDefinitions>
            <!-- 行标题 -->
            <TextBlock Grid.Column="0" Text="澳大利亚 (Australia)" Style="{StaticResource RowTitleStyle}"/>
            <!-- 人口饼图 -->
            <Grid Grid.Column="1" Style="{StaticResource ChartContainerStyle}">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <TextBlock Grid.Row="0" Text="人种构成" Style="{StaticResource ChartTitleStyle}"/>
                <lvc:PieChart Grid.Row="1" Series="{Binding AustraliaDemographicSeries}" 
                              LegendLocation="Bottom" Height="150"/>
            </Grid>
            <!-- 年龄趋势图 -->
            <Grid Grid.Column="2" Style="{StaticResource ChartContainerStyle}">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <TextBlock Grid.Row="0" Text="年龄分布趋势" Style="{StaticResource ChartTitleStyle}"/>
                <lvc:CartesianChart Grid.Row="1" Series="{Binding AustraliaAgeTrendSeries}" Height="150">
                    <lvc:CartesianChart.AxisX>
                        <lvc:Axis Labels="{Binding AustraliaAgeGroupLabels}"/>
                    </lvc:CartesianChart.AxisX>
                    <lvc:CartesianChart.AxisY>
                        <lvc:Axis Title="占比(%)"/>
                    </lvc:CartesianChart.AxisY>
                </lvc:CartesianChart>
            </Grid>
            <!-- 收入柱状图 -->
            <Grid Grid.Column="3" Style="{StaticResource ChartContainerStyle}">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <TextBlock Grid.Row="0" Text="收入分布" Style="{StaticResource ChartTitleStyle}"/>
                <lvc:CartesianChart Grid.Row="1" Series="{Binding AustraliaIncomeSeries}" Height="150">
                    <lvc:CartesianChart.AxisX>
                        <lvc:Axis Labels="{Binding AustraliaIncomeRangeLabels}"/>
                    </lvc:CartesianChart.AxisX>
                    <lvc:CartesianChart.AxisY>
                        <lvc:Axis Title="人口(百万)"/>
                    </lvc:CartesianChart.AxisY>
                </lvc:CartesianChart>
            </Grid>
        </Grid>

        <!-- 第四行:英国数据 -->
        <Grid Grid.Row="3" Margin="0 10 0 0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="150"/>
                <ColumnDefinition Width="1*"/>
                <ColumnDefinition Width="1*"/>
                <ColumnDefinition Width="1*"/>
            </Grid.ColumnDefinitions>
            <!-- 行标题 -->
            <TextBlock Grid.Column="0" Text="英国 (UK)" Style="{StaticResource RowTitleStyle}"/>
            <!-- 人口饼图 -->
            <Grid Grid.Column="1" Style="{StaticResource ChartContainerStyle}">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <TextBlock Grid.Row="0" Text="人种构成" Style="{StaticResource ChartTitleStyle}"/>
                <lvc:PieChart Grid.Row="1" Series="{Binding UKDemographicSeries}" 
                              LegendLocation="Bottom" Height="150"/>
            </Grid>
            <!-- 年龄趋势图 -->
            <Grid Grid.Column="2" Style="{StaticResource ChartContainerStyle}">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <TextBlock Grid.Row="0" Text="年龄分布趋势" Style="{StaticResource ChartTitleStyle}"/>
                <lvc:CartesianChart Grid.Row="1" Series="{Binding UKAgeTrendSeries}" Height="150">
                    <lvc:CartesianChart.AxisX>
                        <lvc:Axis Labels="{Binding UKAgeGroupLabels}"/>
                    </lvc:CartesianChart.AxisX>
                    <lvc:CartesianChart.AxisY>
                        <lvc:Axis Title="占比(%)"/>
                    </lvc:CartesianChart.AxisY>
                </lvc:CartesianChart>
            </Grid>
            <!-- 收入柱状图 -->
            <Grid Grid.Column="3" Style="{StaticResource ChartContainerStyle}">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <TextBlock Grid.Row="0" Text="收入分布" Style="{StaticResource ChartTitleStyle}"/>
                <lvc:CartesianChart Grid.Row="1" Series="{Binding UKIncomeSeries}" Height="150">
                    <lvc:CartesianChart.AxisX>
                        <lvc:Axis Labels="{Binding UKIncomeRangeLabels}"/>
                    </lvc:CartesianChart.AxisX>
                    <lvc:CartesianChart.AxisY>
                        <lvc:Axis Title="人口(百万)"/>
                    </lvc:CartesianChart.AxisY>
                </lvc:CartesianChart>
            </Grid>
        </Grid>
    </Grid>
</UserControl>

using LiveCharts;
using LiveCharts.Wpf;
using Prism.Mvvm;
using Prism.Regions;
using Shared.Models;
using Shared.Services;
using System;
using System.Collections.Generic;
using System.Linq;

namespace HomeModule
{
    public class HomeViewModel : BindableBase, INavigationAware
    {
        #region 依赖注入&核心数据
        private readonly MockDataService _mockDataService;

        // 四个国家的完整数据
        private CountryStatsModel _usaData;
        private CountryStatsModel _canadaData;
        private CountryStatsModel _australiaData;
        private CountryStatsModel _ukData;
        #endregion

        #region 图表属性(添加私有字段+显式PropertyChanged通知)
        // 美国
        private SeriesCollection _usADemographicSeries = new();
        public SeriesCollection USADemographicSeries
        {
            get => _usADemographicSeries;
            set => SetProperty(ref _usADemographicSeries, value);
        }

        private SeriesCollection _usAAgeTrendSeries = new();
        public SeriesCollection USAAgeTrendSeries
        {
            get => _usAAgeTrendSeries;
            set => SetProperty(ref _usAAgeTrendSeries, value);
        }

        private SeriesCollection _usAIncomeSeries = new();
        public SeriesCollection USAIncomeSeries
        {
            get => _usAIncomeSeries;
            set => SetProperty(ref _usAIncomeSeries, value);
        }

        private List<string> _usAAgeGroupLabels = new();
        public List<string> USAAgeGroupLabels
        {
            get => _usAAgeGroupLabels;
            set => SetProperty(ref _usAAgeGroupLabels, value);
        }

        private List<string> _usAIncomeRangeLabels = new();
        public List<string> USAIncomeRangeLabels
        {
            get => _usAIncomeRangeLabels;
            set => SetProperty(ref _usAIncomeRangeLabels, value);
        }

        // 加拿大
        private SeriesCollection _canadaDemographicSeries = new();
        public SeriesCollection CanadaDemographicSeries
        {
            get => _canadaDemographicSeries;
            set => SetProperty(ref _canadaDemographicSeries, value);
        }

        private SeriesCollection _canadaAgeTrendSeries = new();
        public SeriesCollection CanadaAgeTrendSeries
        {
            get => _canadaAgeTrendSeries;
            set => SetProperty(ref _canadaAgeTrendSeries, value);
        }

        private SeriesCollection _canadaIncomeSeries = new();
        public SeriesCollection CanadaIncomeSeries
        {
            get => _canadaIncomeSeries;
            set => SetProperty(ref _canadaIncomeSeries, value);
        }

        private List<string> _canadaAgeGroupLabels = new();
        public List<string> CanadaAgeGroupLabels
        {
            get => _canadaAgeGroupLabels;
            set => SetProperty(ref _canadaAgeGroupLabels, value);
        }

        private List<string> _canadaIncomeRangeLabels = new();
        public List<string> CanadaIncomeRangeLabels
        {
            get => _canadaIncomeRangeLabels;
            set => SetProperty(ref _canadaIncomeRangeLabels, value);
        }

        // 澳大利亚
        private SeriesCollection _australiaDemographicSeries = new();
        public SeriesCollection AustraliaDemographicSeries
        {
            get => _australiaDemographicSeries;
            set => SetProperty(ref _australiaDemographicSeries, value);
        }

        private SeriesCollection _australiaAgeTrendSeries = new();
        public SeriesCollection AustraliaAgeTrendSeries
        {
            get => _australiaAgeTrendSeries;
            set => SetProperty(ref _australiaAgeTrendSeries, value);
        }

        private SeriesCollection _australiaIncomeSeries = new();
        public SeriesCollection AustraliaIncomeSeries
        {
            get => _australiaIncomeSeries;
            set => SetProperty(ref _australiaIncomeSeries, value);
        }

        private List<string> _australiaAgeGroupLabels = new();
        public List<string> AustraliaAgeGroupLabels
        {
            get => _australiaAgeGroupLabels;
            set => SetProperty(ref _australiaAgeGroupLabels, value);
        }

        private List<string> _australiaIncomeRangeLabels = new();
        public List<string> AustraliaIncomeRangeLabels
        {
            get => _australiaIncomeRangeLabels;
            set => SetProperty(ref _australiaIncomeRangeLabels, value);
        }

        // 英国
        private SeriesCollection _ukDemographicSeries = new();
        public SeriesCollection UKDemographicSeries
        {
            get => _ukDemographicSeries;
            set => SetProperty(ref _ukDemographicSeries, value);
        }

        private SeriesCollection _ukAgeTrendSeries = new();
        public SeriesCollection UKAgeTrendSeries
        {
            get => _ukAgeTrendSeries;
            set => SetProperty(ref _ukAgeTrendSeries, value);
        }

        private SeriesCollection _ukIncomeSeries = new();
        public SeriesCollection UKIncomeSeries
        {
            get => _ukIncomeSeries;
            set => SetProperty(ref _ukIncomeSeries, value);
        }

        private List<string> _ukAgeGroupLabels = new();
        public List<string> UKAgeGroupLabels
        {
            get => _ukAgeGroupLabels;
            set => SetProperty(ref _ukAgeGroupLabels, value);
        }

        private List<string> _ukIncomeRangeLabels = new();
        public List<string> UKIncomeRangeLabels
        {
            get => _ukIncomeRangeLabels;
            set => SetProperty(ref _ukIncomeRangeLabels, value);
        }
        #endregion

        /// <summary>
        /// 构造函数(注入Mock数据服务)
        /// </summary>
        public HomeViewModel(MockDataService mockDataService)
        {
            _mockDataService = mockDataService;
            // 调试日志:确认构造函数执行
            System.Diagnostics.Debug.WriteLine("✅ HomeViewModel 构造函数执行");
        }

        #region 导航生命周期&数据加载
        public void OnNavigatedTo(NavigationContext navigationContext)
        {
            try
            {
                // 调试日志:确认OnNavigatedTo执行
                System.Diagnostics.Debug.WriteLine("✅ HomeViewModel OnNavigatedTo 执行");

                // 1. 获取四个国家的Mock数据,并验证是否为空
                _usaData = _mockDataService.GetCountryData("usa");
                _canadaData = _mockDataService.GetCountryData("canada");
                _australiaData = _mockDataService.GetCountryData("australia");
                _ukData = _mockDataService.GetCountryData("uk");

                System.Diagnostics.Debug.WriteLine($"📌 USA数据是否为空:{_usaData == null}");
                System.Diagnostics.Debug.WriteLine($"📌 Canada数据是否为空:{_canadaData == null}");
                System.Diagnostics.Debug.WriteLine($"📌 Australia数据是否为空:{_australiaData == null}");
                System.Diagnostics.Debug.WriteLine($"📌 UK数据是否为空:{_ukData == null}");

                if (_usaData == null || _canadaData == null || _australiaData == null || _ukData == null)
                {
                    System.Diagnostics.Debug.WriteLine("❌ MockDataService返回空数据,请检查GetCountryData方法");
                    return;
                }

                // 2. 初始化所有国家的图表数据
                InitUSACharts();
                InitCanadaCharts();
                InitAustraliaCharts();
                InitUKCharts();

                System.Diagnostics.Debug.WriteLine("✅ 所有图表数据初始化完成");
            }
            catch (Exception ex)
            {
                // 捕获异常并输出,避免吞掉错误
                System.Diagnostics.Debug.WriteLine($"❌ OnNavigatedTo执行异常:{ex.Message}\n{ex.StackTrace}");
            }
        }

        public bool IsNavigationTarget(NavigationContext navigationContext) => true;
        public void OnNavigatedFrom(NavigationContext navigationContext) { }
        #endregion

        #region 图表初始化方法(按国家拆分,便于维护)
        /// <summary>
        /// 初始化美国图表数据
        /// </summary>
        private void InitUSACharts()
        {
            // 1.人种构成饼图:显式创建SeriesCollection并逐个Add PieSeries
            var seriesCollection = new SeriesCollection();
            foreach (var d in _usaData.DemographicData)
            {
                var pieSeries = new PieSeries
                {
                    Title = d.Ethnicity,
                    DataLabels = true,
                    Values = new ChartValues<double> { d.Percentage } // 确保Values有数据
                };
                // 显式Add到SeriesCollection
                seriesCollection.Add(pieSeries);
            }

            // 赋值并触发属性通知
            USADemographicSeries = seriesCollection;

            // 调试日志:确认SeriesCollection的Count
            System.Diagnostics.Debug.WriteLine($"📌 美国饼图SeriesCollection.Count:{USADemographicSeries.Count}");

            // 2. 年龄趋势折线图
            USAAgeTrendSeries = new SeriesCollection
            {
                new LineSeries
                {
                    Title = "年龄占比",
                    Values = new ChartValues<double>(_usaData.AgeTrendData.Select(x => x.PopulationRatio)),
                    LineSmoothness = 1, // 平滑曲线
                    PointGeometry = DefaultGeometries.Circle,
                    PointGeometrySize = 4
                }
            };
            USAAgeGroupLabels = _usaData.AgeTrendData.Select(x => x.AgeGroup.ToString()).ToList();

            // 3. 收入分布柱状图
            USAIncomeSeries = new SeriesCollection
            {
                new ColumnSeries
                {
                    Title = "人口数",
                    Values = new ChartValues<double>(_usaData.IncomeData.Select(x => x.PopulationCount))
                }
            };
            USAIncomeRangeLabels = _usaData.IncomeData.Select(x => x.IncomeRange).ToList();

            System.Diagnostics.Debug.WriteLine($"✅ 美国图表数据初始化:饼图系列数={USADemographicSeries.Count},折线图数据量={USAAgeTrendSeries[0].Values.Count}");
        }

        /// <summary>
        /// 初始化加拿大图表数据
        /// </summary>
        private void InitCanadaCharts()
        {
            // 1. 人种构成饼图
            var seriesCollection = new SeriesCollection();
            foreach (var d in _canadaData.DemographicData)
            {
                var pieSeries = new PieSeries
                {
                    Title = d.Ethnicity,
                    DataLabels = true,
                    Values = new ChartValues<double> { d.Percentage } // 确保Values有数据
                };
                // 显式Add到SeriesCollection
                seriesCollection.Add(pieSeries);
            }

            // 赋值并触发属性通知
            CanadaDemographicSeries = seriesCollection;

            // 调试日志:确认SeriesCollection的Count
            System.Diagnostics.Debug.WriteLine($"📌 加拿大饼图SeriesCollection.Count:{CanadaDemographicSeries.Count}");

            // 2. 年龄趋势折线图
            CanadaAgeTrendSeries = new SeriesCollection
            {
                new LineSeries
                {
                    Title = "年龄占比",
                    Values = new ChartValues<double>(_canadaData.AgeTrendData.Select(x => x.PopulationRatio)),
                    LineSmoothness = 1,
                    PointGeometry = DefaultGeometries.Circle,
                    PointGeometrySize = 4
                }
            };
            CanadaAgeGroupLabels = _canadaData.AgeTrendData.Select(x => x.AgeGroup.ToString()).ToList();

            // 3. 收入分布柱状图
            CanadaIncomeSeries = new SeriesCollection
            {
                new ColumnSeries
                {
                    Title = "人口数",
                    Values = new ChartValues<double>(_canadaData.IncomeData.Select(x => x.PopulationCount))
                }
            };
            CanadaIncomeRangeLabels = _canadaData.IncomeData.Select(x => x.IncomeRange).ToList();

            System.Diagnostics.Debug.WriteLine($"✅ 加拿大图表数据初始化:饼图系列数={CanadaDemographicSeries.Count}");
        }

        /// <summary>
        /// 初始化澳大利亚图表数据
        /// </summary>
        private void InitAustraliaCharts()
        {
            var seriesCollection = new SeriesCollection();
            foreach (var d in _australiaData.DemographicData)
            {
                var pieSeries = new PieSeries
                {
                    Title = d.Ethnicity,
                    DataLabels = true,
                    Values = new ChartValues<double> { d.Percentage } // 确保Values有数据
                };
                // 显式Add到SeriesCollection
                seriesCollection.Add(pieSeries);
            }

            // 赋值并触发属性通知
            AustraliaDemographicSeries = seriesCollection;

            // 调试日志:确认SeriesCollection的Count
            System.Diagnostics.Debug.WriteLine($"📌 澳大利亚饼图SeriesCollection.Count:{AustraliaDemographicSeries.Count}");

            // 2. 年龄趋势折线图
            AustraliaAgeTrendSeries = new SeriesCollection
            {
                new LineSeries
                {
                    Title = "年龄占比",
                    Values = new ChartValues<double>(_australiaData.AgeTrendData.Select(x => x.PopulationRatio)),
                    LineSmoothness = 1,
                    PointGeometry = DefaultGeometries.Circle,
                    PointGeometrySize = 4
                }
            };
            AustraliaAgeGroupLabels = _australiaData.AgeTrendData.Select(x => x.AgeGroup.ToString()).ToList();

            // 3. 收入分布柱状图
            AustraliaIncomeSeries = new SeriesCollection
            {
                new ColumnSeries
                {
                    Title = "人口数",
                    Values = new ChartValues<double>(_australiaData.IncomeData.Select(x => x.PopulationCount))
                }
            };
            AustraliaIncomeRangeLabels = _australiaData.IncomeData.Select(x => x.IncomeRange).ToList();

            System.Diagnostics.Debug.WriteLine($"✅ 澳大利亚图表数据初始化:饼图系列数={AustraliaDemographicSeries.Count}");
        }

        /// <summary>
        /// 初始化英国图表数据
        /// </summary>
        private void InitUKCharts()
        {
            var seriesCollection = new SeriesCollection();
            foreach (var d in _ukData.DemographicData)
            {
                var pieSeries = new PieSeries
                {
                    Title = d.Ethnicity,
                    DataLabels = true,
                    Values = new ChartValues<double> { d.Percentage } // 确保Values有数据
                };
                // 显式Add到SeriesCollection
                seriesCollection.Add(pieSeries);
            }

            // 赋值并触发属性通知
            UKDemographicSeries = seriesCollection;

            // 2. 年龄趋势折线图
            UKAgeTrendSeries = new SeriesCollection
            {
                new LineSeries
                {
                    Title = "年龄占比",
                    Values = new ChartValues<double>(_ukData.AgeTrendData.Select(x => x.PopulationRatio)),
                    LineSmoothness = 1,
                    PointGeometry = DefaultGeometries.Circle,
                    PointGeometrySize = 4
                }
            };
            UKAgeGroupLabels = _ukData.AgeTrendData.Select(x => x.AgeGroup.ToString()).ToList();

            // 3. 收入分布柱状图
            UKIncomeSeries = new SeriesCollection
            {
                new ColumnSeries
                {
                    Title = "人口数",
                    Values = new ChartValues<double>(_ukData.IncomeData.Select(x => x.PopulationCount))
                }
            };
            UKIncomeRangeLabels = _ukData.IncomeData.Select(x => x.IncomeRange).ToList();

            System.Diagnostics.Debug.WriteLine($"✅ 英国图表数据初始化:饼图系列数={UKDemographicSeries.Count}");
        }
        #endregion
    }
}

 

 

//Shell
<prism:PrismApplication x:Class="Shell.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:Shell"
             xmlns:prism="http://prismlibrary.com/">
</prism:PrismApplication>



using CanadaModule;
using LiveCharts.Wpf;
using Prism.DryIoc;
using Prism.Ioc;
using Prism.Modularity;
using System.Configuration;
using System.Data;
using System.Reflection;
using System.Windows;
using System.Windows.Shapes;

namespace Shell
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : PrismApplication
    {
        protected override Window CreateShell()
        {
            return Container.Resolve<MainWindow>();
        }

        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            //注冊mock数据服务
            containerRegistry.RegisterSingleton<Shared.Services.MockDataService>(() => Shared.Services.MockDataService.Instance);
        }

        protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
        {
            moduleCatalog.AddModule<HomeModule.HomeModule>();
            moduleCatalog.AddModule<USAModule.USAModule>();
            moduleCatalog.AddModule<CanadaModule.CanadaModule>();
            moduleCatalog.AddModule<AustraliaModule.AustraliaModule>();
            moduleCatalog.AddModule<UKModule.UKModule>();
            base.ConfigureModuleCatalog(moduleCatalog);
        }
    }

}



<Window x:Class="Shell.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Shell"
        xmlns:prism="http://www.codeplex.com/prism"
        prism:ViewModelLocator.AutoWireViewModel="True"
        WindowState="Maximized"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <local:ViewNameMatchConverter x:Key="ViewNameMatchConverter"/>

        <!-- 2. 修正导航按钮样式(用MultiDataTrigger替代原DataTrigger) -->
        <Style x:Key="NavButtonStyle" TargetType="Button">
            <Setter Property="Height" Value="50"/>
            <Setter Property="Background" Value="#34495E"/>
            <Setter Property="Foreground" Value="White"/>
            <Setter Property="FontSize" Value="30"/>
            <Setter Property="Padding" Value="10 5"/>
            <Setter Property="BorderThickness" Value="0"/>
            <Setter Property="HorizontalAlignment" Value="Stretch"/>
            <Setter Property="FontWeight" Value="Normal"/>
            <Style.Triggers>
                <!-- 原有鼠标悬浮效果 -->
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Background" Value="#1ABC9C"/>
                    <Setter Property="Height" Value="70"/>
                </Trigger>

                <!-- 核心:MultiDataTrigger实现选中高亮(解决Value不能绑定的问题) -->
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition>
                            <Condition.Binding>
                                <!-- 多值绑定:同时传当前视图名 + 按钮参数 -->
                                <MultiBinding Converter="{StaticResource ViewNameMatchConverter}">
                                    <!-- 绑定窗口ViewModel的CurrentViewName -->
                                    <Binding RelativeSource="{RelativeSource AncestorType=Window}" 
                                             Path="DataContext.CurrentViewName"/>
                                    <!-- 绑定当前按钮的CommandParameter -->
                                    <Binding RelativeSource="{RelativeSource Self}" 
                                             Path="CommandParameter"/>
                                </MultiBinding>
                            </Condition.Binding>
                            <Condition.Value>True</Condition.Value>
                        </Condition>
                    </MultiDataTrigger.Conditions>

                    <!-- 选中高亮样式(可自定义) -->
                    <Setter Property="Background" Value="Cyan"/>
                    <!-- 红色背景 -->
                    <Setter Property="Height" Value="70"/>
                    <!-- 高度放大 -->
                    <Setter Property="FontWeight" Value="Bold"/>
                    <!-- 字体加粗 -->
                    <Setter Property="Foreground" Value="Yellow"/>
                    <!-- 黄色字体 -->
                    <Setter Property="BorderBrush" Value="White"/>
                    <!-- 白色边框 -->
                    <Setter Property="BorderThickness" Value="2"/>
                    <!-- 边框宽度 -->
                </MultiDataTrigger>
            </Style.Triggers>
        </Style>


        <!--<Style x:Key="NavButtonStyle" TargetType="Button">
            <Setter Property="Height" Value="50"/>
            <Setter Property="Background" Value="#34495E"/>
            <Setter Property="Foreground" Value="White"/>
            <Setter Property="FontSize" Value="30"/>
            <Setter Property="Padding" Value="10 5"/>
            <Setter Property="BorderThickness" Value="0"/>
            <Setter Property="HorizontalAlignment" Value="Stretch"/>
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Background" Value="#1ABC9C"/>
                    <Setter Property="Height" Value="70"/>
                </Trigger>
                -->
        <!-- 核心:选中高亮触发 -->
        <!--
                <DataTrigger                    
                    Binding="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.CurrentViewName}"
                    Value="{Binding RelativeSource={RelativeSource Self}, Path=CommandParameter}">
                    -->
        <!-- 高亮样式(可自定义) -->
        <!--
                    <Setter Property="Background" Value="#E74C3C"/>
                    -->
        <!-- 红色高亮 -->
        <!--
                    <Setter Property="Height" Value="70"/>
                    -->
        <!-- 高度放大 -->
        <!--
                    <Setter Property="FontWeight" Value="Bold"/>
                    -->
        <!-- 字体加粗 -->
        <!--
                    <Setter Property="Foreground" Value="Yellow"/>
                    -->
        <!-- 字体黄色 -->
        <!--
                    <Setter Property="BorderBrush" Value="White"/>
                    -->
        <!-- 白色边框 -->
        <!--
                    <Setter Property="BorderThickness" Value="2"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>-->

        <Style TargetType="TextBlock">
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Background" Value="#1ABC9C"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <Grid>
        <!--左侧导航栏-->
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="200"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <!--导航菜单-->
        <StackPanel Grid.Column="0" Background="#2C3E50" Margin="10">
            <TextBlock Text="导航菜单" FontSize="36" Foreground="White"
                       HorizontalAlignment="Center"/>
            <Button Content="首页" Command="{Binding NavigateCommand}"
                    CommandParameter="HomeView" Style="{StaticResource NavButtonStyle}"
                    Margin="0"/>
            <Button Content="USA" Command="{Binding NavigateCommand}"
                    CommandParameter="USAView" Style="{StaticResource NavButtonStyle}"
                    Margin="0"/>
            <Button Content="Canada" Command="{Binding NavigateCommand}"
                    CommandParameter="CanadaView" Style="{StaticResource NavButtonStyle}"
                    Margin="0"/>
            <Button Content="Australia" Command="{Binding NavigateCommand}"
                    CommandParameter="AustraliaView" Style="{StaticResource NavButtonStyle}"
                    Margin="0"/>
            <Button Content="UK" Command="{Binding NavigateCommand}"
                    CommandParameter="UKView" Style="{StaticResource NavButtonStyle}"
                    Margin="0"/>
        </StackPanel>

        <ContentControl Grid.Column="1"
                        prism:RegionManager.RegionName="ContentRegion"
                        Margin="2"/>
    </Grid>
</Window>




using Prism.Commands;
using Prism.Mvvm;
using Prism.Regions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Shell
{
    public class MainWindowViewModel : BindableBase
    {
        private readonly IRegionManager regionManager;

        // 跟踪当前选中的视图名称(初始为HomeView,默认高亮首页)
        private string _currentViewName = "HomeView";
        public string CurrentViewName
        {
            get => _currentViewName;
            set => SetProperty(ref _currentViewName, value); // 触发UI更新
        }

        public DelegateCommand<string> NavigateCommand { get; }
        public MainWindowViewModel(IRegionManager regionManagerValue)
        {
            regionManager = regionManagerValue;
            NavigateCommand = new DelegateCommand<string>(NavigateCommandExecuted);
            NavigateCommandExecuted("HomeView");
        }

        private void NavigateCommandExecuted(string viewName)
        {
            if (string.IsNullOrEmpty(viewName))
            {
                return;
            }

            // 1. 导航到指定视图
            regionManager.RequestNavigate("ContentRegion", viewName);
            // 2. 更新当前选中视图名称(用于按钮高亮)
            CurrentViewName = viewName;
        }
    }
}


using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;

namespace Shell
{
    /// <summary>
    /// 比较当前视图名和按钮参数是否一致的转换器
    /// </summary>
    public class ViewNameMatchConverter : IMultiValueConverter
    {
        /// <summary>
        /// 转换逻辑:value[0]=CurrentViewName,value[1]=CommandParameter
        /// </summary>
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            // 校验参数完整性
            if (values.Length < 2 || values[0] == null || values[1] == null)
                return false;

            // 比较两个值是否相等(忽略大小写)
            string currentView = values[0].ToString();
            string buttonParam = values[1].ToString();
            return currentView.Equals(buttonParam, StringComparison.Ordinal);
        }

        // 反向转换无需实现(导航选中状态无需反向修改)
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException("无需反向转换");
        }
    }
}

 

 

 

 

using Prism.Ioc;
using Prism.Modularity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace UKModule
{
    public class UKModule : IModule
    {
        public void OnInitialized(IContainerProvider containerProvider)
        {

        }

        public void RegisterTypes(IContainerRegistry containerRegistry)
        {
            containerRegistry.RegisterForNavigation<UKView>();
        }
    }
}

<UserControl x:Class="UKModule.UKView"
             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:UKModule"
                          xmlns:prism="http://prismlibrary.com/"
             xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
             xmlns:shared="clr-namespace:Shared.Models;assembly=Shared"
             prism:ViewModelLocator.AutoWireViewModel="True"
             mc:Ignorable="d" 
             d:DesignHeight="700" d:DesignWidth="900">
    <UserControl.Resources>
        <!-- 转换器:布尔值转可见性 -->
        <BooleanToVisibilityConverter x:Key="BoolToVis"/>
    </UserControl.Resources>

    <Grid Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <!-- 1. 页面标题 -->
        <TextBlock Grid.Row="0" Text="{Binding CountryData.CountryName}" 
                   FontSize="20" FontWeight="Bold" Margin="0 0 0 10"/>

        <!-- 2. 图表区域(饼图+折线图+柱状图) -->
        <Grid Grid.Row="1" Margin="0 10 0 10">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="1*"/>
                <ColumnDefinition Width="1*"/>
                <ColumnDefinition Width="1*"/>
            </Grid.ColumnDefinitions>

            <!-- 人种构成饼图 -->
            <Grid Grid.Column="0" Margin="0 0 10 0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <TextBlock Text="人种构成" FontSize="14" FontWeight="SemiBold" Margin="0 0 0 5"/>
                <lvc:PieChart Grid.Row="1" Series="{Binding DemographicSeries}" 
                              LegendLocation="Bottom"/>
            </Grid>

            <!-- 年龄趋势折线图 -->
            <Grid Grid.Column="1" Margin="5 0 5 0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <TextBlock Text="年龄分布趋势" FontSize="14" FontWeight="SemiBold" Margin="0 0 0 5"/>
                <lvc:CartesianChart Grid.Row="1" Series="{Binding AgeTrendSeries}">
                    <lvc:CartesianChart.AxisX>
                        <lvc:Axis Title="年龄组" Labels="{Binding AgeGroupLabels}"/>
                    </lvc:CartesianChart.AxisX>
                    <lvc:CartesianChart.AxisY>
                        <lvc:Axis Title="人口占比(%)"/>
                    </lvc:CartesianChart.AxisY>
                </lvc:CartesianChart>
            </Grid>

            <!-- 收入分布柱状图 -->
            <Grid Grid.Column="2" Margin="10 0 0 0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <TextBlock Text="收入分布" FontSize="14" FontWeight="SemiBold" Margin="0 0 0 5"/>
                <lvc:CartesianChart Grid.Row="1" Series="{Binding IncomeSeries}">
                    <lvc:CartesianChart.AxisX>
                        <lvc:Axis Title="收入区间(USD)" Labels="{Binding IncomeRangeLabels}"/>
                    </lvc:CartesianChart.AxisX>
                    <lvc:CartesianChart.AxisY>
                        <lvc:Axis Title="人口数(百万)"/>
                    </lvc:CartesianChart.AxisY>
                </lvc:CartesianChart>
            </Grid>
        </Grid>

        <DataGrid Grid.Row="3" ItemsSource="{Binding PagedCityData}" AutoGenerateColumns="False"
                  CanUserAddRows="False" CanUserDeleteRows="False"
                  FontSize="30">
            <DataGrid.Resources>
                <Style TargetType="{x:Type DataGridTextColumn}">
                    <Setter Property="Width" Value="*"/>
                </Style>
            </DataGrid.Resources>
            <DataGrid.Columns>
                <DataGridTextColumn Header="城市名" Binding="{Binding CityName}" 
                                    Visibility="{Binding ShowCityName, Converter={StaticResource BoolToVis}}"/>
                <DataGridTextColumn Header="人口" Binding="{Binding Population, StringFormat=N0}" 
                                    Visibility="{Binding ShowPopulation, Converter={StaticResource BoolToVis}}"/>
                <DataGridTextColumn Header="人均收入(USD)" Binding="{Binding PerCapitaIncome, StringFormat=C2}" 
                                    Visibility="{Binding ShowPerCapitaIncome, Converter={StaticResource BoolToVis}}"/>
                <DataGridTextColumn Header="面积(km²)" Binding="{Binding Area, StringFormat=N1}" 
                                    Visibility="{Binding ShowArea, Converter={StaticResource BoolToVis}}"/>
                <DataGridTextColumn Header="GDP(亿美元)" Binding="{Binding GDP, StringFormat=N1}" 
                                    Visibility="{Binding ShowGDP, Converter={StaticResource BoolToVis}}"/>
                <DataGridTextColumn Header="科研开支(亿USD)" Binding="{Binding RDSpending, StringFormat=N1}" 
                                    Visibility="{Binding ShowRDSpending, Converter={StaticResource BoolToVis}}"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</UserControl>

using LiveCharts;
using LiveCharts.Wpf;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Regions;
using Shared.Models;
using Shared.Services;
using System;
using System.Collections.Generic;
using System.Diagnostics.PerformanceData;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace UKModule
{
    public class UKViewModel : BindableBase, INavigationAware
    {
        #region 依赖注入&核心字段
        private readonly MockDataService _mockDataService;
        private CountryStatsModel _countryData = new();
        private List<CityStatsModel> _allCityData = new();
        private List<CityStatsModel> _pagedCityData = new();

        // 分页参数
        private int _currentPage = 1;
        private int _pageSize = 5;
        private int _totalPages;

        // 列显隐控制
        private bool _showCityName = true;
        private bool _showPopulation = true;
        private bool _showPerCapitaIncome = true;
        private bool _showArea = true;
        private bool _showGDP = true;
        private bool _showRDSpending = true;

        // 图表数据
        private SeriesCollection _demographicSeries = new();
        private SeriesCollection _ageTrendSeries = new();
        private SeriesCollection _incomeSeries = new();
        private List<string> _ageGroupLabels = new();
        private List<string> _incomeRangeLabels = new();
        #endregion

        #region 绑定属性
        public CountryStatsModel CountryData
        {
            get => _countryData;
            set => SetProperty(ref _countryData, value);
        }

        public List<CityStatsModel> PagedCityData
        {
            get => _pagedCityData;
            set => SetProperty(ref _pagedCityData, value);
        }

        // 分页属性
        public int CurrentPage
        {
            get => _currentPage;
            set
            {
                if (SetProperty(ref _currentPage, value))
                {
                    UpdatePagedData();
                    RaisePropertyChanged(nameof(CanGoPrevious));
                    RaisePropertyChanged(nameof(CanGoNext));
                }
            }
        }

        public int TotalPages
        {
            get => _totalPages;
            set => SetProperty(ref _totalPages, value);
        }

        public bool CanGoPrevious => CurrentPage > 1;
        public bool CanGoNext => CurrentPage < TotalPages;

        // 列显隐属性
        public bool ShowCityName
        {
            get => _showCityName;
            set => SetProperty(ref _showCityName, value);
        }

        public bool ShowPopulation
        {
            get => _showPopulation;
            set => SetProperty(ref _showPopulation, value);
        }

        public bool ShowPerCapitaIncome
        {
            get => _showPerCapitaIncome;
            set => SetProperty(ref _showPerCapitaIncome, value);
        }

        public bool ShowArea
        {
            get => _showArea;
            set => SetProperty(ref _showArea, value);
        }

        public bool ShowGDP
        {
            get => _showGDP;
            set => SetProperty(ref _showGDP, value);
        }

        public bool ShowRDSpending
        {
            get => _showRDSpending;
            set => SetProperty(ref _showRDSpending, value);
        }

        // 图表绑定属性
        public SeriesCollection DemographicSeries
        {
            get => _demographicSeries;
            set => SetProperty(ref _demographicSeries, value);
        }

        public SeriesCollection AgeTrendSeries
        {
            get => _ageTrendSeries;
            set => SetProperty(ref _ageTrendSeries, value);
        }

        public SeriesCollection IncomeSeries
        {
            get => _incomeSeries;
            set => SetProperty(ref _incomeSeries, value);
        }

        public List<string> AgeGroupLabels
        {
            get => _ageGroupLabels;
            set => SetProperty(ref _ageGroupLabels, value);
        }

        public List<string> IncomeRangeLabels
        {
            get => _incomeRangeLabels;
            set => SetProperty(ref _incomeRangeLabels, value);
        }

        // 分页命令
        public ICommand PreviousPageCommand => new DelegateCommand(() => CurrentPage--);
        public ICommand NextPageCommand => new DelegateCommand(() => CurrentPage++);
        #endregion

        public UKViewModel(MockDataService mockDataService)
        {
            _mockDataService = mockDataService;
        }

        #region 导航&数据加载
        public void OnNavigatedTo(NavigationContext navigationContext)
        {
            // 加载USA数据
            CountryData = _mockDataService.GetCountryData("UK");
            _allCityData = CountryData.CityData;
            PagedCityData = _allCityData.Take(10).ToList();
            // 初始化分页
            TotalPages = (int)Math.Ceiling((double)_allCityData.Count / _pageSize);
            CurrentPage = 1;

            // 初始化图表
            InitCharts();
        }

        public bool IsNavigationTarget(NavigationContext navigationContext) => true;
        public void OnNavigatedFrom(NavigationContext navigationContext) { }
        #endregion

        #region 私有方法
        // 初始化图表数据
        private void InitCharts()
        {
            // 1. 人种构成饼图
            DemographicSeries = new SeriesCollection();
            foreach (var item in CountryData.DemographicData)
            {
                DemographicSeries.Add(new PieSeries
                {
                    Title = item.Ethnicity,
                    Values = new ChartValues<double> { item.Percentage },
                    DataLabels = true
                });
            }

            // 2. 年龄趋势折线图
            AgeTrendSeries = new SeriesCollection
            {
                new LineSeries
                {
                    Title = "年龄占比",
                    Values = new ChartValues<double>(CountryData.AgeTrendData.Select(x => x.PopulationRatio)),
                    LineSmoothness = 1, // 平滑曲线
                    PointGeometry = DefaultGeometries.Circle,
                    PointGeometrySize = 5
                }
            };
            AgeGroupLabels = CountryData.AgeTrendData.Select(x => x.AgeGroup.ToString()).ToList();

            // 3. 收入分布柱状图
            IncomeSeries = new SeriesCollection
            {
                new ColumnSeries
                {
                    Title= "人口数",
                    Values= new ChartValues<double>(CountryData.IncomeData.Select(x => x.PopulationCount))
                }
            };
            IncomeRangeLabels = CountryData.IncomeData.Select(x => x.IncomeRange).ToList();
        }

        // 更新分页数据
        private void UpdatePagedData()
        {
            PagedCityData = _allCityData
                .Skip((CurrentPage - 1) * _pageSize)
                .Take(_pageSize)
                .ToList();
        }
        #endregion
    }
}

 

 

//USAModule
using Prism.Ioc;
using Prism.Modularity;
using Prism.Regions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace USAModule
{
    public class USAModule : IModule
    {
        public void OnInitialized(IContainerProvider containerProvider)
        {

        }

        public void RegisterTypes(IContainerRegistry containerRegistry)
        {
            containerRegistry.RegisterForNavigation<USAView>();
        }
    }
}


<UserControl x:Class="USAModule.USAView"
             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:USAModule"
             xmlns:prism="http://prismlibrary.com/"
             xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
             xmlns:shared="clr-namespace:Shared.Models;assembly=Shared"
             prism:ViewModelLocator.AutoWireViewModel="True"
             mc:Ignorable="d" 
             d:DesignHeight="700" d:DesignWidth="900">
    <UserControl.Resources>
        <!-- 转换器:布尔值转可见性 -->
        <BooleanToVisibilityConverter x:Key="BoolToVis"/>
    </UserControl.Resources>

    <Grid Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <!-- 1. 页面标题 -->
        <TextBlock Grid.Row="0" Text="{Binding CountryData.CountryName}" 
                   FontSize="20" FontWeight="Bold" Margin="0 0 0 10"/>

        <!-- 2. 图表区域(饼图+折线图+柱状图) -->
        <Grid Grid.Row="1" Margin="0 10 0 10">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="1*"/>
                <ColumnDefinition Width="1*"/>
                <ColumnDefinition Width="1*"/>
            </Grid.ColumnDefinitions>

            <!-- 人种构成饼图 -->
            <Grid Grid.Column="0" Margin="0 0 10 0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <TextBlock Text="人种构成" FontSize="14" FontWeight="SemiBold" Margin="0 0 0 5"/>
                <lvc:PieChart Grid.Row="1" Series="{Binding DemographicSeries}" 
                              LegendLocation="Bottom"/>
            </Grid>

            <!-- 年龄趋势折线图 -->
            <Grid Grid.Column="1" Margin="5 0 5 0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <TextBlock Text="年龄分布趋势" FontSize="14" FontWeight="SemiBold" Margin="0 0 0 5"/>
                <lvc:CartesianChart Grid.Row="1" Series="{Binding AgeTrendSeries}">
                    <lvc:CartesianChart.AxisX>
                        <lvc:Axis Title="年龄组" Labels="{Binding AgeGroupLabels}"/>
                    </lvc:CartesianChart.AxisX>
                    <lvc:CartesianChart.AxisY>
                        <lvc:Axis Title="人口占比(%)"/>
                    </lvc:CartesianChart.AxisY>
                </lvc:CartesianChart>
            </Grid>

            <!-- 收入分布柱状图 -->
            <Grid Grid.Column="2" Margin="10 0 0 0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <TextBlock Text="收入分布" FontSize="14" FontWeight="SemiBold" Margin="0 0 0 5"/>
                <lvc:CartesianChart Grid.Row="1" Series="{Binding IncomeSeries}">
                    <lvc:CartesianChart.AxisX>
                        <lvc:Axis Title="收入区间(USD)" Labels="{Binding IncomeRangeLabels}"/>
                    </lvc:CartesianChart.AxisX>
                    <lvc:CartesianChart.AxisY>
                        <lvc:Axis Title="人口数(百万)"/>
                    </lvc:CartesianChart.AxisY>
                </lvc:CartesianChart>
            </Grid>
        </Grid>

        <DataGrid Grid.Row="3" ItemsSource="{Binding PagedCityData}" AutoGenerateColumns="False"
                  CanUserAddRows="False" CanUserDeleteRows="False"
                  FontSize="30">
            <DataGrid.Resources>
                <Style TargetType="{x:Type DataGridTextColumn}">
                    <Setter Property="Width" Value="*"/>
                </Style>
            </DataGrid.Resources>
            <DataGrid.Columns>
                <DataGridTextColumn Header="城市名" Binding="{Binding CityName}" 
                                    Visibility="{Binding ShowCityName, Converter={StaticResource BoolToVis}}"/>
                <DataGridTextColumn Header="人口" Binding="{Binding Population, StringFormat=N0}" 
                                    Visibility="{Binding ShowPopulation, Converter={StaticResource BoolToVis}}"/>
                <DataGridTextColumn Header="人均收入(USD)" Binding="{Binding PerCapitaIncome, StringFormat=C2}" 
                                    Visibility="{Binding ShowPerCapitaIncome, Converter={StaticResource BoolToVis}}"/>
                <DataGridTextColumn Header="面积(km²)" Binding="{Binding Area, StringFormat=N1}" 
                                    Visibility="{Binding ShowArea, Converter={StaticResource BoolToVis}}"/>
                <DataGridTextColumn Header="GDP(亿美元)" Binding="{Binding GDP, StringFormat=N1}" 
                                    Visibility="{Binding ShowGDP, Converter={StaticResource BoolToVis}}"/>
                <DataGridTextColumn Header="科研开支(亿USD)" Binding="{Binding RDSpending, StringFormat=N1}" 
                                    Visibility="{Binding ShowRDSpending, Converter={StaticResource BoolToVis}}"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</UserControl>



using LiveCharts;
using LiveCharts.Wpf;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Regions;
using Shared.Models;
using Shared.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace USAModule
{
    public class USAViewModel : BindableBase, INavigationAware
    {
        #region 依赖注入&核心字段
        private readonly MockDataService _mockDataService;
        private CountryStatsModel _countryData = new();
        private List<CityStatsModel> _allCityData = new();
        private List<CityStatsModel> _pagedCityData = new();

        // 分页参数
        private int _currentPage = 1;
        private int _pageSize = 5;
        private int _totalPages;

        // 列显隐控制
        private bool _showCityName = true;
        private bool _showPopulation = true;
        private bool _showPerCapitaIncome = true;
        private bool _showArea = true;
        private bool _showGDP = true;
        private bool _showRDSpending = true;

        // 图表数据
        private SeriesCollection _demographicSeries = new();
        private SeriesCollection _ageTrendSeries = new();
        private SeriesCollection _incomeSeries = new();
        private List<string> _ageGroupLabels = new();
        private List<string> _incomeRangeLabels = new();
        #endregion

        #region 绑定属性
        public CountryStatsModel CountryData
        {
            get => _countryData;
            set => SetProperty(ref _countryData, value);
        }

        public List<CityStatsModel> PagedCityData
        {
            get => _pagedCityData;
            set => SetProperty(ref _pagedCityData, value);
        }

        // 分页属性
        public int CurrentPage
        {
            get => _currentPage;
            set
            {
                if (SetProperty(ref _currentPage, value))
                {
                    UpdatePagedData();
                    RaisePropertyChanged(nameof(CanGoPrevious));
                    RaisePropertyChanged(nameof(CanGoNext));
                }
            }
        }

        public int TotalPages
        {
            get => _totalPages;
            set => SetProperty(ref _totalPages, value);
        }

        public bool CanGoPrevious => CurrentPage > 1;
        public bool CanGoNext => CurrentPage < TotalPages;

        // 列显隐属性
        public bool ShowCityName
        {
            get => _showCityName;
            set => SetProperty(ref _showCityName, value);
        }

        public bool ShowPopulation
        {
            get => _showPopulation;
            set => SetProperty(ref _showPopulation, value);
        }

        public bool ShowPerCapitaIncome
        {
            get => _showPerCapitaIncome;
            set => SetProperty(ref _showPerCapitaIncome, value);
        }

        public bool ShowArea
        {
            get => _showArea;
            set => SetProperty(ref _showArea, value);
        }

        public bool ShowGDP
        {
            get => _showGDP;
            set => SetProperty(ref _showGDP, value);
        }

        public bool ShowRDSpending
        {
            get => _showRDSpending;
            set => SetProperty(ref _showRDSpending, value);
        }

        // 图表绑定属性
        public SeriesCollection DemographicSeries
        {
            get => _demographicSeries;
            set => SetProperty(ref _demographicSeries, value);
        }

        public SeriesCollection AgeTrendSeries
        {
            get => _ageTrendSeries;
            set => SetProperty(ref _ageTrendSeries, value);
        }

        public SeriesCollection IncomeSeries
        {
            get => _incomeSeries;
            set => SetProperty(ref _incomeSeries, value);
        }

        public List<string> AgeGroupLabels
        {
            get => _ageGroupLabels;
            set => SetProperty(ref _ageGroupLabels, value);
        }

        public List<string> IncomeRangeLabels
        {
            get => _incomeRangeLabels;
            set => SetProperty(ref _incomeRangeLabels, value);
        }

        // 分页命令
        public ICommand PreviousPageCommand => new DelegateCommand(() => CurrentPage--);
        public ICommand NextPageCommand => new DelegateCommand(() => CurrentPage++);
        #endregion

        public USAViewModel(MockDataService mockDataService)
        {
            _mockDataService = mockDataService;
        }

        #region 导航&数据加载
        public void OnNavigatedTo(NavigationContext navigationContext)
        {
            // 加载USA数据
            CountryData = _mockDataService.GetCountryData("USA");
            _allCityData = CountryData.CityData;
            PagedCityData = _allCityData.Take(10).ToList();
            // 初始化分页
            TotalPages = (int)Math.Ceiling((double)_allCityData.Count / _pageSize);
            CurrentPage = 1;

            // 初始化图表
            InitCharts();
        }

        public bool IsNavigationTarget(NavigationContext navigationContext) => true;
        public void OnNavigatedFrom(NavigationContext navigationContext) { }
        #endregion

        #region 私有方法
        // 初始化图表数据
        private void InitCharts()
        {
            // 1. 人种构成饼图
            DemographicSeries = new SeriesCollection();
            foreach (var item in CountryData.DemographicData)
            {
                DemographicSeries.Add(new PieSeries
                {
                    Title = item.Ethnicity,
                    Values = new ChartValues<double> { item.Percentage },
                    DataLabels = true
                });
            }

            // 2. 年龄趋势折线图
            AgeTrendSeries = new SeriesCollection
            {
                new LineSeries
                {
                    Title = "年龄占比",
                    Values = new ChartValues<double>(CountryData.AgeTrendData.Select(x => x.PopulationRatio)),
                    LineSmoothness = 1, // 平滑曲线
                    PointGeometry = DefaultGeometries.Circle,
                    PointGeometrySize = 5
                }
            };
            AgeGroupLabels = CountryData.AgeTrendData.Select(x => x.AgeGroup.ToString()).ToList();

            // 3. 收入分布柱状图
            IncomeSeries = new SeriesCollection
            {
                new ColumnSeries
                {
                    Title= "人口数",
                    Values= new ChartValues<double>(CountryData.IncomeData.Select(x => x.PopulationCount))
                }
            };
            IncomeRangeLabels = CountryData.IncomeData.Select(x => x.IncomeRange).ToList();
        }

        // 更新分页数据
        private void UpdatePagedData()
        {
            PagedCityData = _allCityData
                .Skip((CurrentPage - 1) * _pageSize)
                .Take(_pageSize)
                .ToList();
        }
        #endregion
    }

 

 

The whole code architecture as below

image

 

 

 

Shell/Shell.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net10.0-windows</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <UseWPF>true</UseWPF>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="livecharts.wpf" Version="0.9.7" />
    <PackageReference Include="Prism.DryIoc" Version="8.1.97" />
    <PackageReference Include="Prism.Wpf" Version="8.1.97" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\AustraliaModule\AustraliaModule.csproj" />
    <ProjectReference Include="..\CanadaModule\CanadaModule.csproj" />
    <ProjectReference Include="..\HomeModule\HomeModule.csproj" />
    <ProjectReference Include="..\Shared\Shared.csproj" />
    <ProjectReference Include="..\UKModule\UKModule.csproj" />
    <ProjectReference Include="..\USAModule\USAModule.csproj" />
  </ItemGroup>

</Project>

 

 

USAModule\USAModule.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net10.0-windows</TargetFramework>
    <Nullable>enable</Nullable>
    <UseWPF>true</UseWPF>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="livecharts.wpf" Version="0.9.7" />
    <PackageReference Include="Prism.DryIoc" Version="8.1.97" />
    <PackageReference Include="Prism.Wpf" Version="8.1.97" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\Shared\Shared.csproj" />
  </ItemGroup>

</Project>

 

 

 var seriesCollection = new SeriesCollection();
 foreach (var d in _usaData.DemographicData)
 {
     var pieSeries = new PieSeries
     {
         Title = d.Ethnicity,
         DataLabels = true,
         Values = new ChartValues<double> { d.Percentage } // 确保Values有数据
     };
     // 显式Add到SeriesCollection
     seriesCollection.Add(pieSeries);
 }

 // 赋值并触发属性通知
 USADemographicSeries = seriesCollection;

 // 调试日志:确认SeriesCollection的Count
 System.Diagnostics.Debug.WriteLine($"📌 美国饼图SeriesCollection.Count:{USADemographicSeries.Count}");

 

posted @ 2026-01-11 18:49  FredGrit  阅读(1)  评论(0)    收藏  举报