ThinkGeo Cloud
ThinkGeo UI Controls
ThinkGeo Open Source
Help and Support
External Resources
ThinkGeo Cloud
ThinkGeo UI Controls
ThinkGeo Open Source
Help and Support
External Resources
<Window x:Class="ThinkGeo.MapSuite.USDemographicMap.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:ThinkGeo.MapSuite.USDemographicMap" xmlns:wpf="clr-namespace:ThinkGeo.MapSuite.WpfDesktopEdition;assembly=WpfDesktopEdition" Title="US Demographic Map" Height="675" Width="1155" WindowState="Maximized" Icon="/MapSuiteUSDemographicMap;Component/Image/MapSuite.ico" Loaded="Window_Loaded"> <Window.Resources> <ResourceDictionary> <Style x:Key="ColumnItemList" TargetType="ListBox"> <Style.Resources> <Style TargetType="ListBoxItem" BasedOn="{StaticResource ColumnDataSelectionItem}" /> </Style.Resources> <Setter Property="SelectionMode" Value="Single"/> <Setter Property="Margin" Value="20 5 0 0" /> <Setter Property="ItemsSource" Value="{Binding Columns}" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate> <StackPanel IsItemsHost="True" /> </ControlTemplate> </Setter.Value> </Setter> <Setter Property="ItemTemplate"> <Setter.Value> <DataTemplate> <Grid Width="250" Margin="0 3 0 3"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="auto" /> <ColumnDefinition Width="auto" /> </Grid.ColumnDefinitions> <TextBlock Grid.Column="0" Text="{Binding Alias}" Style="{StaticResource bodyText1}" /> <StackPanel Grid.Column="1" VerticalAlignment="Center" Orientation="Horizontal"> <Button Width="20" ToolTip="Present the data in Value Circles." Template="{StaticResource ImageButtonTemplate}" Margin="{StaticResource TitleImageButtonMargin}" VerticalAlignment="Center" Click="ValueCirclesClick" Content="/MapSuiteUSDemographicMap;Component/Image/valueCircle.png" Tag="/MapSuiteUSDemographicMap;Component/Image/valueCircle_Disable.png" /> <Button Width="20" ToolTip="Present the data in Thematic Colors." Template="{StaticResource ImageButtonTemplate}" Margin="{StaticResource TitleImageButtonMargin}" VerticalAlignment="Center" Click="ThematicColorsClick" Content="/MapSuiteUSDemographicMap;Component/Image/thematic.png" Tag="/MapSuiteUSDemographicMap;Component/Image/thematic_Disable.png" /> <Button Width="20" ToolTip="Present the data with Dot Density." Template="{StaticResource ImageButtonTemplate}" Margin="{StaticResource TitleImageButtonMargin}" VerticalAlignment="Center" Click="DotDensityClick" Content="/MapSuiteUSDemographicMap;Component/Image/dotdensity.png" Tag="/MapSuiteUSDemographicMap;Component/Image/dotdensity_Disable.png" /> </StackPanel> <CheckBox Grid.Column="2" Click="ColumnCheckBox_Click" Style="{StaticResource msCheckBox}" IsChecked="{Binding IsSelected,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Visibility="{Binding CheckBoxVisiblity}"/> </Grid> </DataTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary> </Window.Resources> <Grid Style="{StaticResource sampleBody}"> <Grid.RowDefinitions> <RowDefinition Height="auto" /> <RowDefinition Height="*" /> <RowDefinition Height="auto" /> </Grid.RowDefinitions> <Border BorderThickness="0,0,0,5" Padding="10" CornerRadius="2" KeyboardNavigation.TabNavigation="Local" KeyboardNavigation.DirectionalNavigation="Contained" KeyboardNavigation.TabIndex="2"> <Border.Background> <LinearGradientBrush StartPoint="0,0" EndPoint="0,1"> <LinearGradientBrush.GradientStops> <GradientStop Offset="0" Color="#ffffff" /> <GradientStop Offset="0.4" Color="#fafafa" /> <GradientStop Offset="0.55" Color="#f2f2f2" /> <GradientStop Offset="0.6" Color="#f0f0f0" /> <GradientStop Offset="0.9" Color="#e2e2e2" /> </LinearGradientBrush.GradientStops> </LinearGradientBrush> </Border.Background> <Border.BorderBrush> <LinearGradientBrush StartPoint="0,0" EndPoint="0,1"> <LinearGradientBrush.GradientStops> <GradientStop Offset="0.85" Color="#5c707d" /> <GradientStop Offset="1" Color="#305c707d" /> </LinearGradientBrush.GradientStops> </LinearGradientBrush> </Border.BorderBrush> <StackPanel Orientation="Horizontal"> <TextBlock Style="{StaticResource ControlFont}" Margin="{StaticResource TitleMargin}"> <Run FontSize="16">Map Suite</Run> <Run FontSize="20">US Demographic Map</Run> </TextBlock> </StackPanel> </Border> <Grid Grid.Row="1"> <Grid.ColumnDefinitions> <ColumnDefinition Width="auto" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Grid Grid.Column="0" Grid.Row="0"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="auto" /> <ColumnDefinition Width="5" /> </Grid.ColumnDefinitions> <Grid x:Name="gridDockPanel" HorizontalAlignment="Left"> <Grid.Resources> <Style TargetType="Grid"> <Style.Triggers> <DataTrigger Binding="{Binding ElementName=CollapseToggleButton,Path=IsChecked}" Value="true"> <Setter Property="Visibility" Value="Collapsed" /> </DataTrigger> </Style.Triggers> </Style> </Grid.Resources> <Grid> <Grid.RowDefinitions> <RowDefinition Height="40" /> <RowDefinition Height="*" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Grid Grid.Row="0"> <TextBlock Style="{StaticResource h4}" Text="Select data for display:" HorizontalAlignment="Left" VerticalAlignment="Center" Width="290" Margin="5 0 0 0" TextWrapping="Wrap" /> </Grid> <Border Grid.Row="1" BorderBrush="LightGray" BorderThickness="1" CornerRadius="5" Margin="5 10 0 0"> <ListBox Margin="5 5 5 5" BorderBrush="Transparent" SelectionMode="Single" ItemsSource="{Binding CategoryList}" SelectedItem="{Binding SelectedCategory,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"> <ListBox.Resources> <Style BasedOn="{StaticResource CategoryDataSelectionItem}" TargetType="{x:Type ListBoxItem}"/> </ListBox.Resources> <ListBox.ItemTemplateSelector> <local:CategoryItemTemplateSelector> <local:CategoryItemTemplateSelector.DefaultDataTemplate> <DataTemplate> <Grid Width="280"> <Grid.RowDefinitions> <RowDefinition Height="45" /> <RowDefinition Height="auto" /> </Grid.RowDefinitions> <Border BorderBrush="LightGray" Grid.Row="0" BorderThickness="0 0 0 1"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="auto" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="auto" /> </Grid.ColumnDefinitions> <Image Grid.Column="0" Source="{Binding CategoryImage}" Style="{StaticResource msImage}" /> <TextBlock Text="{Binding Title}" Grid.Column="1" Style="{StaticResource CategoryHeaderText}" /> <Button Template="{StaticResource ImageButtonTemplate}" Margin="{StaticResource PieChartImageButtonMargin}" Visibility="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged, Converter={StaticResource BoolToVisibility}}" Height="20" Width="20" Grid.Column="2" VerticalAlignment="Center" ToolTip="Display pie charts on the map representing the breakdown of all data points selected below." IsEnabled="{Binding CanUsePieView,Mode=TwoWay}" Click="PieChartClick" Content="/MapSuiteUSDemographicMap;Component/Image/pie.png" Tag="/MapSuiteUSDemographicMap;Component/Image/pie_Disable.png" /> </Grid> </Border> <ListBox Grid.Row="1" Visibility="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged, Converter={StaticResource BoolToVisibility}}" Style="{StaticResource ColumnItemList}" /> </Grid> </DataTemplate> </local:CategoryItemTemplateSelector.DefaultDataTemplate> <local:CategoryItemTemplateSelector.CustomDataTemplate> <DataTemplate> <Grid Width="280"> <Grid.RowDefinitions> <RowDefinition Height="45" /> <RowDefinition Height="auto" /> </Grid.RowDefinitions> <Border BorderBrush="LightGray" Grid.Row="0" BorderThickness="0 0 0 1"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="auto" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="auto" /> </Grid.ColumnDefinitions> <Image Grid.Column="0" Source="{Binding CategoryImage}" Style="{StaticResource msImage}" /> <TextBlock Text="{Binding Title}" Grid.Column="1" Style="{StaticResource CategoryHeaderText}" /> <Button Template="{StaticResource ImageButtonTemplate}" Margin="{StaticResource PieChartImageButtonMargin}" Visibility="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged, Converter={StaticResource BoolToVisibility}}" Height="20" Width="20" Grid.Column="2" VerticalAlignment="Center" ToolTip="Display pie charts on the map representing the breakdown of all data points selected below." IsEnabled="{Binding CanUsePieView,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Click="PieChartClick" Content="/MapSuiteUSDemographicMap;Component/Image/pie.png" Tag="/MapSuiteUSDemographicMap;Component/Image/pie_Disable.png" /> </Grid> </Border> <Grid Grid.Row="1" Margin="0 5 0 0" Visibility="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged, Converter={StaticResource BoolToVisibility}}"> <Grid.RowDefinitions> <RowDefinition Height="auto" /> <RowDefinition Height="auto" /> </Grid.RowDefinitions> <StackPanel Grid.Row="0" HorizontalAlignment="Left" Orientation="Horizontal"> <TextBox Width="180" IsEnabled="False" Text="{Binding CustomDataFilePathName,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" /> <Button Margin="10 0 0 0" Content="Browse" Width="80" Click="BrowseCustomDataClick" /> </StackPanel> <ListBox Grid.Row="1" Style="{StaticResource ColumnItemList}" /> </Grid> </Grid> </DataTemplate> </local:CategoryItemTemplateSelector.CustomDataTemplate> </local:CategoryItemTemplateSelector> </ListBox.ItemTemplateSelector> </ListBox> </Border> <Grid Grid.Row="2" Margin="5 10 0 10" VerticalAlignment="Top"> <Grid.RowDefinitions> <RowDefinition Height="auto" /> <RowDefinition Height="auto" /> </Grid.RowDefinitions> <Grid Grid.Row="0"> <Grid.RowDefinitions> <RowDefinition Height="35"/> <RowDefinition Height="auto"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="140"/> <ColumnDefinition Width="150"/> </Grid.ColumnDefinitions> <TextBlock VerticalAlignment="Center" Grid.Row="0" Grid.Column="0" Style="{StaticResource bodyHeaderText2}" Text="{Binding DisplayColorText}"/> <ComboBox x:Name="cmbSelectColor" Grid.Row="0" Grid.Column="1" Style="{StaticResource ColorSelectBox}" SelectedItem="{Binding SelectedColorItem,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding GeoColorList}" /> <Grid Visibility="{Binding ThematicVisibility}" Grid.Row="1" Grid.ColumnSpan="2"> <Grid.RowDefinitions> <RowDefinition Height="35"/> <RowDefinition Height="35"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="140"/> <ColumnDefinition Width="150"/> </Grid.ColumnDefinitions> <TextBlock VerticalAlignment="Center" Grid.Row="0" Grid.Column="0" Style="{StaticResource bodyHeaderText2}" Text="Display End Color:" /> <ComboBox Grid.Row="0" Grid.Column="1" Style="{StaticResource ColorSelectBox}" SelectedItem="{Binding SelectedEndColorItem,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding GeoColorList}" /> <TextBlock VerticalAlignment="Center" Grid.Row="1" Grid.Column="0" Style="{StaticResource bodyHeaderText2}" Text="ColorWheelDirection:" /> <ComboBox Grid.Row="1" Grid.Column="1" Style="{StaticResource ColorSelectBox}" ItemsSource="{Binding ColorWheelDirections}" SelectedItem="{Binding SelectedColorWheelDirection,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" > <ComboBox.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding .}" /> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox> </Grid> </Grid> <Grid Visibility="{Binding DotDensityVisibility}" Grid.Row="2" > <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="auto" /> </Grid.ColumnDefinitions> <TextBlock Grid.Column="0" VerticalAlignment="Top" Margin="0 13 0 0" Style="{StaticResource bodyHeaderText2}" Text="DotDensity Unit:" /> <Grid Grid.Column="1" Width="170" Margin="0 10 0 0" HorizontalAlignment="Left"> <Grid.RowDefinitions> <RowDefinition Height="auto" /> <RowDefinition Height="2" /> <RowDefinition Height="auto" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="auto" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="auto" /> </Grid.ColumnDefinitions> <Slider Grid.Row="0" Grid.ColumnSpan="3" Maximum="5" Minimum="1" Value="3" Width="160" HorizontalAlignment="Right" Focusable="False" x:Name="sldDotDensityDemographicStyleDotsCount" IsSnapToTickEnabled="True" TickPlacement="BottomRight" Thumb.DragCompleted="DotDensityStyleDotsCountSlider_DragCompleted" ButtonBase.Click="DotDensityStyleDotsCountSlider_Click" ValueChanged="DotDensityStyleDotsCountSlider_ValueChanged" /> <TextBlock Grid.Row="2" Grid.Column="0" Style="{StaticResource bodyText1}" FontSize="10" Text="Fewer dots" /> <TextBlock Grid.Row="2" Grid.Column="2" Style="{StaticResource bodyText1}" FontSize="10" Text="More dots" /> </Grid> </Grid> <Grid Visibility="{Binding ValueCircleVisibility}" Grid.Row="2" > <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="auto" /> </Grid.ColumnDefinitions> <TextBlock Grid.Column="0" Style="{StaticResource bodyHeaderText2}" Text="MAGNIFICATION:" VerticalAlignment="Bottom" Margin="0 0 0 3" /> <Slider x:Name="sldValueCircleDemographicStyleRadius" Grid.Column="1" Margin="0 10 0 0" Width="160" Maximum="5" Minimum="1" Value="3" Focusable="False" IsSnapToTickEnabled="True" TickPlacement="BottomRight" ValueChanged="ValueCircleStyleRadiusSlider_ValueChanged" Thumb.DragCompleted="ValueCircleStyleRadiusSlider_DragCompleted" ButtonBase.Click="ValueCircleStyleRadiusSlider_Click" /> </Grid> </Grid> </Grid> </Grid> <ToggleButton x:Name="CollapseToggleButton" Content="/Image/Collapse.gif" Tag="/Image/Expand.gif" Template="{StaticResource ToggleButtonTemplate}" Grid.Row="0" Grid.Column="1" VerticalAlignment="Center" Cursor="Hand" Background="Transparent" BorderBrush="Transparent" /> <Rectangle Grid.Row="0" Grid.Column="2"> <Rectangle.Fill> <LinearGradientBrush StartPoint="0,0" EndPoint="1,0"> <GradientStop Color="#5c707d" Offset="0"></GradientStop> <GradientStop Color="#305c707d" Offset="1"></GradientStop> </LinearGradientBrush> </Rectangle.Fill> </Rectangle> </Grid> <wpf:WpfMap x:Name="wpfMap" Grid.Column="1" Panel.ZIndex="-1"/> </Grid> <Grid Grid.Row="2"> <Border BorderBrush="Gray" BorderThickness="0 1 0 0"> <StatusBar Height="30"> <StatusBarItem HorizontalContentAlignment="Stretch"> <Grid HorizontalAlignment="Right"> <Grid.ColumnDefinitions> <ColumnDefinition Width="auto" /> <ColumnDefinition Width="5" /> <ColumnDefinition Width="auto" /> </Grid.ColumnDefinitions> <TextBlock Text="{Binding CoordinateX,StringFormat=X:{0:N6}}" HorizontalAlignment="Right" Width="75" VerticalAlignment="Center" Grid.Column="0"/> <TextBlock Text="{Binding CoordinateY,StringFormat=Y:{0:N6}}" VerticalAlignment="Center" Width="75" Grid.Column="2" /> </Grid> </StatusBarItem> </StatusBar> </Border> </Grid> </Grid> </Window>
using Microsoft.Win32; using System.Linq; using System.Windows; using System.Windows.Controls.Primitives; using ThinkGeo.MapSuite.Core; namespace ThinkGeo.MapSuite.USDemographicMap { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { private bool isSliderClicked; private MapModel mapModel; private MainWindowViewModel mainWindowViewModel; public MainWindow() { InitializeComponent(); } private void Window_Loaded(object sender, RoutedEventArgs e) { mapModel = new MapModel(wpfMap); mainWindowViewModel = new MainWindowViewModel(mapModel); DataContext = mainWindowViewModel; mainWindowViewModel.UpdateMap(); mapModel.MapControl.Refresh(); } private void ColumnCheckBox_Click(object sender, RoutedEventArgs e) { if (mainWindowViewModel.SelectedCategory.Columns.Count(d => d.IsSelected) >= 2) { mainWindowViewModel.SelectedCategory.CanUsePieView = true; mainWindowViewModel.CreatePieDemographicStyle(); mainWindowViewModel.UpdateMap(); } else { mainWindowViewModel.SelectedCategory.CanUsePieView = false; } } private void DotDensityStyleDotsCountSlider_Click(object sender, RoutedEventArgs e) { isSliderClicked = true; } private void DotDensityStyleDotsCountSlider_DragCompleted(object sender, DragCompletedEventArgs e) { mainWindowViewModel.DotDensityDemographicStyle.DotDensityValue = 50 * (sldDotDensityDemographicStyleDotsCount.Value / 3); mainWindowViewModel.UpdateMap(); } private void DotDensityStyleDotsCountSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) { if (isSliderClicked) { mainWindowViewModel.DotDensityDemographicStyle.DotDensityValue = 50 * (sldDotDensityDemographicStyleDotsCount.Value / 3); mainWindowViewModel.UpdateMap(); isSliderClicked = false; } } private void ValueCircleStyleRadiusSlider_Click(object sender, RoutedEventArgs e) { isSliderClicked = true; } private void ValueCircleStyleRadiusSlider_DragCompleted(object sender, DragCompletedEventArgs e) { mainWindowViewModel.ValueCircleDemographicStyle.RadiusRatio = sldValueCircleDemographicStyleRadius.Value / 3; mainWindowViewModel.UpdateMap(); } private void ValueCircleStyleRadiusSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) { if (isSliderClicked) { mainWindowViewModel.ValueCircleDemographicStyle.RadiusRatio = sldValueCircleDemographicStyleRadius.Value / 3; mainWindowViewModel.UpdateMap(); isSliderClicked = false; } } private void ValueCirclesClick(object sender, RoutedEventArgs e) { CollapseControls(); mainWindowViewModel.ValueCircleVisibility = Visibility.Visible; ColumnViewModel columnViewModel = sender.GetDataContext<ColumnViewModel>(); if (columnViewModel != null && !(columnViewModel.Parent is CustomDataCategoryViewModel)) { mapModel.DefaultFeatureLayer = mapModel.CensusStateFeatureLayer; } else { mapModel.DefaultFeatureLayer = mapModel.CustomDataFeatureLayer; } RenderDemographicStyle(sender, mainWindowViewModel.ValueCircleDemographicStyle); } private void ThematicColorsClick(object sender, RoutedEventArgs e) { CollapseControls(); mainWindowViewModel.ThematicVisibility = Visibility.Visible; mainWindowViewModel.DisplayColorText = "Display Start Color:"; ColumnViewModel columnViewModel = sender.GetDataContext<ColumnViewModel>(); if (columnViewModel != null && !(columnViewModel.Parent is CustomDataCategoryViewModel)) { mapModel.DefaultFeatureLayer = mapModel.CensusStateFeatureLayer; } else { mapModel.DefaultFeatureLayer = mapModel.CustomDataFeatureLayer; } RenderDemographicStyle(sender, mainWindowViewModel.ThematicDemographicStyle); } private void DotDensityClick(object sender, RoutedEventArgs e) { CollapseControls(); mainWindowViewModel.DotDensityVisibility = Visibility.Visible; ColumnViewModel columnViewModel = sender.GetDataContext<ColumnViewModel>(); if (columnViewModel != null && !(columnViewModel.Parent is CustomDataCategoryViewModel)) { mapModel.DefaultFeatureLayer = mapModel.CensusStateFeatureLayer; } else { mapModel.DefaultFeatureLayer = mapModel.CustomDataFeatureLayer; } RenderDemographicStyle(sender, mainWindowViewModel.DotDensityDemographicStyle); } private void PieChartClick(object sender, RoutedEventArgs e) { CollapseControls(); if (sender.GetDataContext<CustomDataCategoryViewModel>() == null) { mapModel.DefaultFeatureLayer = mapModel.CensusStateFeatureLayer; } else { mapModel.DefaultFeatureLayer = mapModel.CustomDataFeatureLayer; } mainWindowViewModel.CreatePieDemographicStyle(); mainWindowViewModel.UpdateMap(); } private void CollapseControls() { mainWindowViewModel.DotDensityVisibility = Visibility.Collapsed; mainWindowViewModel.ValueCircleVisibility = Visibility.Collapsed; mainWindowViewModel.ThematicVisibility = Visibility.Collapsed; mainWindowViewModel.DisplayColorText = "Display Color:"; } private void RenderDemographicStyle(object sender, DemographicStyleBuilder demographicStyleBuilder) { FrameworkElement frameworkElement = (FrameworkElement)sender; ColumnViewModel columnViewModel = (ColumnViewModel)frameworkElement.DataContext; columnViewModel.IsSelected = true; foreach (var item in mainWindowViewModel.SelectedCategory.Columns) { item.CheckBoxVisiblity = Visibility.Hidden; } mainWindowViewModel.UpdateUIControls(demographicStyleBuilder); mainWindowViewModel.CurrentStyleBuilder.SelectedColumns.Clear(); mainWindowViewModel.CurrentStyleBuilder.SelectedColumns.Add(columnViewModel.ColumnName); mapModel.LegendTitle = columnViewModel.LegendTitle; mainWindowViewModel.UpdateMap(); } private void BrowseCustomDataClick(object sender, RoutedEventArgs e) { CustomDataCategoryViewModel customDataCategoryViewModel = ((FrameworkElement)sender).DataContext as CustomDataCategoryViewModel; OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.Filter = "Shape File(*.shp)|*.shp"; if (openFileDialog.ShowDialog().GetValueOrDefault()) { ShapeFileFeatureLayer shapeFileFeatureLayer = new ShapeFileFeatureLayer(openFileDialog.FileName); shapeFileFeatureLayer.Open(); if (shapeFileFeatureLayer.GetShapeFileType() == ShapeFileType.Polygon) { customDataCategoryViewModel.CustomDataFilePathName = openFileDialog.FileName; customDataCategoryViewModel.Columns.Clear(); foreach (DbfColumn dbfColumn in shapeFileFeatureLayer.FeatureSource.GetColumns().OfType<DbfColumn>()) { if (dbfColumn.ColumnType == DbfColumnType.Float || dbfColumn.ColumnType == DbfColumnType.Numeric || dbfColumn.ColumnType == DbfColumnType.Double || dbfColumn.ColumnType == DbfColumnType.DoubleInBinary || dbfColumn.ColumnType == DbfColumnType.Integer || dbfColumn.ColumnType == DbfColumnType.IntegerInBinary) { customDataCategoryViewModel.Columns.Add(new ColumnViewModel(dbfColumn.ColumnName, dbfColumn.ColumnName) { LegendTitle = dbfColumn.ColumnName, Parent = customDataCategoryViewModel }); } } customDataCategoryViewModel.CanUsePieView = customDataCategoryViewModel.Columns.Count >= 2; mapModel.CustomDataFeatureLayer = shapeFileFeatureLayer; } else { MessageBox.Show("The shapefile must be polygon type, please try another one.", "Warning"); } } } } }
using System.Windows; using ThinkGeo.MapSuite.Core; using ThinkGeo.MapSuite.USDemographicMap.Properties; using ThinkGeo.MapSuite.WpfDesktopEdition; namespace ThinkGeo.MapSuite.USDemographicMap { public class MapModel { private static RectangleShape globeExtent = new RectangleShape(-128.090753125, 58.27777578125, -68.149346875, 19.10492421875); private WpfMap mapControl; private LayerOverlay demographicLayerOverlay; private LegendAdornmentLayer legendAdornmentLayer; private HighlightOverlay highlightOverlay; private ShapeFileFeatureLayer censusStateFeatureLayer; private ShapeFileFeatureLayer customDataFeatureLayer; public MapModel() : this(null) { } public MapModel(WpfMap wpfMap) { mapControl = wpfMap; InitializeMap(); InitializeEvents(); } public WpfMap MapControl { get { return mapControl; } set { mapControl = value; } } public HighlightOverlay HighlightOverlay { get { return highlightOverlay; } } public LegendAdornmentLayer LegendAdornmentLayer { get { return legendAdornmentLayer; } } public LayerOverlay DemographicLayerOverlay { get { return demographicLayerOverlay; } } public ShapeFileFeatureLayer DefaultFeatureLayer { get { return (ShapeFileFeatureLayer)demographicLayerOverlay.Layers["DefaultFeatureLayer"]; } set { demographicLayerOverlay.Layers["DefaultFeatureLayer"] = value; } } public ShapeFileFeatureLayer CustomDataFeatureLayer { get { return customDataFeatureLayer; } set { customDataFeatureLayer = value; } } public ShapeFileFeatureLayer CensusStateFeatureLayer { get { return censusStateFeatureLayer; } } public string LegendTitle { get { return legendAdornmentLayer.Title.TextStyle.TextColumnName; } set { legendAdornmentLayer.Title.TextStyle.TextColumnName = value; } } private void InitializeMap() { mapControl.MapTools.Logo.IsEnabled = true; mapControl.MapTools.Logo.Margin = new Thickness(0, 0, 10, 5); mapControl.MapTools.MouseCoordinate.IsEnabled = true; mapControl.MapTools.MouseCoordinate.Visibility = Visibility.Hidden; mapControl.MapTools.MouseCoordinate.Margin = new Thickness(0, 0, 100, 5); mapControl.MapTools.MouseCoordinate.MouseCoordinateType = MouseCoordinateType.Custom; mapControl.Overlays.Add(new WorldMapKitWmsWpfOverlay()); censusStateFeatureLayer = new ShapeFileFeatureLayer(MapSuiteSampleHelper.GetValueFromConfiguration("UsShapefilePath")); censusStateFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; censusStateFeatureLayer.DrawingMarginPercentage = 100; demographicLayerOverlay = new LayerOverlay(); demographicLayerOverlay.TileType = TileType.SingleTile; mapControl.Overlays.Add(demographicLayerOverlay); highlightOverlay = new HighlightOverlay(); mapControl.Overlays.Add(highlightOverlay); legendAdornmentLayer = new LegendAdornmentLayer(); legendAdornmentLayer.Location = AdornmentLocation.LowerLeft; legendAdornmentLayer.Title = new LegendItem(); legendAdornmentLayer.Title.ImageJustificationMode = LegendImageJustificationMode.JustifyImageRight; legendAdornmentLayer.Title.TopPadding = 10; legendAdornmentLayer.Title.BottomPadding = 10; legendAdornmentLayer.Title.TextStyle = new TextStyle("Population", new GeoFont("Segoe UI", 12), new GeoSolidBrush(GeoColor.SimpleColors.Black)); mapControl.AdornmentOverlay.Layers.Add(legendAdornmentLayer); DefaultFeatureLayer = censusStateFeatureLayer; MapControl.CurrentExtent = globeExtent; } private void InitializeEvents() { MapControl.MapTools.PanZoomBar.GlobeButtonClick += PanZoomBar_GlobeButtonClick; } private void PanZoomBar_GlobeButtonClick(object sender, GlobeButtonClickPanZoomBarMapToolEventArgs e) { e.NewExtent = globeExtent; } } }
using System.Drawing; using System.Drawing.Drawing2D; using System.Linq; using System.Windows.Controls; using System.Windows.Media; using ThinkGeo.MapSuite.Core; using ThinkGeo.MapSuite.WpfDesktopEdition; namespace ThinkGeo.MapSuite.USDemographicMap { // This overlay is to highlight a feature when mouse over. public class HighlightOverlay : Overlay { private bool isPanningMap; private double currentScale; private Feature highlightFeature; private InMemoryFeatureLayer highlightFeatureLayer; private TranslateTransform translateTransform; public HighlightOverlay() : base() { isPanningMap = false; highlightFeatureLayer = new InMemoryFeatureLayer(); highlightFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(150, GeoColor.FromHtml("#449FBC")), GeoColor.FromHtml("#014576"), 1); highlightFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; translateTransform = new TranslateTransform(); OverlayCanvas.RenderTransform = translateTransform; } public bool IsPanningMap { get { return isPanningMap; } } public Feature HighlightFeature { get { return highlightFeature; } set { highlightFeature = value; } } protected override void DrawCore(RectangleShape targetExtent, OverlayRefreshType overlayRefreshType) { LayerTile tile = GetTile(targetExtent, MapArguments.ActualWidth, MapArguments.ActualHeight, 0, 0, MapArguments.GetSnappedZoomLevelIndex(targetExtent)); if (overlayRefreshType == OverlayRefreshType.Pan) { isPanningMap = true; PanOverlay(targetExtent); } else { isPanningMap = false; RefreshHighlightLayerTileAndPopup(targetExtent, tile); } } private void RefreshHighlightLayerTileAndPopup(RectangleShape targetExtent, LayerTile tile) { bool isRefreshTile = false; if (translateTransform.X != 0 || translateTransform.Y != 0 || MapArguments.CurrentScale != currentScale) { translateTransform.X = 0; translateTransform.Y = 0; tile = DrawHighlightTile(targetExtent, tile); isRefreshTile = true; } if (highlightFeature != null) { string key = highlightFeature.ColumnValues.Select(k => k.Key).ToArray()[0]; if (highlightFeatureLayer.InternalFeatures.Count == 0 || !highlightFeatureLayer.InternalFeatures[0].ColumnValues.ContainsKey(key) || (highlightFeatureLayer.InternalFeatures.Count > 0 && (highlightFeature.ColumnValues[key] != highlightFeatureLayer.InternalFeatures[0].ColumnValues[key]))) { highlightFeatureLayer.InternalFeatures.Clear(); highlightFeatureLayer.InternalFeatures.Add(highlightFeature); tile = DrawHighlightTile(targetExtent, tile); isRefreshTile = true; } } else if (highlightFeatureLayer.InternalFeatures.Count > 0) { highlightFeatureLayer.InternalFeatures.Clear(); tile = DrawHighlightTile(targetExtent, tile); isRefreshTile = true; } RefreshOverlayCanvas(targetExtent, tile, isRefreshTile); currentScale = MapArguments.CurrentScale; } private void RefreshOverlayCanvas(RectangleShape targetExtent, LayerTile tile, bool isRefreshTile) { if (isRefreshTile) { OverlayCanvas.Children.Clear(); Canvas.SetTop(tile, 0); Canvas.SetLeft(tile, 0); OverlayCanvas.Children.Add(tile); } } private LayerTile DrawHighlightTile(RectangleShape targetExtent, LayerTile tile) { tile.DrawingLayers.Clear(); if (highlightFeatureLayer.InternalFeatures.Count > 0) { tile.DrawingLayers.Add(highlightFeatureLayer); } GeoCanvas geoCanvas = new GdiPlusGeoCanvas() { CompositingQuality = CompositingQuality.HighSpeed, DrawingQuality = DrawingQuality.HighSpeed, SmoothingMode = SmoothingMode.HighSpeed }; Bitmap bitmap = new Bitmap((int)tile.Width, (int)tile.Height); geoCanvas.BeginDrawing(bitmap, targetExtent, MapArguments.MapUnit); tile.Draw(geoCanvas); geoCanvas.EndDrawing(); tile.CommitDrawing(geoCanvas, MapSuiteSampleHelper.GetImageSourceFromNativeImage(bitmap)); return tile; } private LayerTile GetTile(RectangleShape targetExtent, double tileScreenWidth, double tileScreenHeight, long tileColumnIndex, long tileRowIndex, int zoomLevelIndex) { LayerTile layerTile = new LayerTile(); layerTile.Width = tileScreenWidth; layerTile.Height = tileScreenHeight; layerTile.IsAsync = false; layerTile.RowIndex = tileRowIndex; layerTile.ColumnIndex = tileColumnIndex; layerTile.TargetExtent = targetExtent; layerTile.ZoomLevelIndex = zoomLevelIndex; layerTile.DrawingExceptionMode = DrawingExceptionMode; layerTile.Background = new SolidColorBrush(Colors.Transparent); return layerTile; } private void PanOverlay(RectangleShape targetExtent) { if (PreviousExtent != null) { double resolution = MapArguments.CurrentResolution; double worldOffsetX = targetExtent.UpperLeftPoint.X - PreviousExtent.UpperLeftPoint.X; double worldOffsetY = targetExtent.UpperLeftPoint.Y - PreviousExtent.UpperLeftPoint.Y; double screenOffsetX = worldOffsetX / resolution; double screenOffsetY = worldOffsetY / resolution; translateTransform.X -= screenOffsetX; translateTransform.Y += screenOffsetY; } } } }
using System.Windows; namespace ThinkGeo.MapSuite.USDemographicMap { public class ColumnViewModel : ViewModelBase { private bool isSelected; private string alias; private string columnName; private string legendTitle; private Visibility checkBoxVisiblity; private DataCategoryViewModel parent; public ColumnViewModel() : this(string.Empty, string.Empty) { } public ColumnViewModel(string columnName, string displayName) { this.columnName = columnName; alias = displayName; IsSelected = true; CheckBoxVisiblity = Visibility.Hidden; } public string Alias { get { return alias; } set { alias = value; RaisePropertyChanged(() => Alias); } } public string ColumnName { get { return columnName; } set { columnName = value; } } public string LegendTitle { get { return legendTitle; } set { legendTitle = value; } } public bool IsSelected { get { return isSelected; } set { isSelected = value; RaisePropertyChanged(() => IsSelected); } } public Visibility CheckBoxVisiblity { get { return checkBoxVisiblity; } set { checkBoxVisiblity = value; RaisePropertyChanged(() => CheckBoxVisiblity); } } public DataCategoryViewModel Parent { get { return parent; } set { parent = value; } } } }
namespace ThinkGeo.MapSuite.USDemographicMap { public class CustomDataCategoryViewModel : DataCategoryViewModel { private string customDataFilePathName; public CustomDataCategoryViewModel() : base() { CanUsePieView = false; } public string CustomDataFilePathName { get { return customDataFilePathName; } set { customDataFilePathName = value; RaisePropertyChanged(() => CustomDataFilePathName); } } } }
using System.Collections.ObjectModel; using System.Windows.Media.Imaging; namespace ThinkGeo.MapSuite.USDemographicMap { public class DataCategoryViewModel : ViewModelBase { private bool canUsePieView; private string title; private BitmapImage categoryImage; private ObservableCollection<ColumnViewModel> columns; public DataCategoryViewModel() { columns = new ObservableCollection<ColumnViewModel>(); } public bool CanUsePieView { get { return canUsePieView; } set { canUsePieView = value; RaisePropertyChanged(() => CanUsePieView); } } public BitmapImage CategoryImage { get { return categoryImage; } set { categoryImage = value; RaisePropertyChanged(() => CategoryImage); } } public ObservableCollection<ColumnViewModel> Columns { get { return columns; } } public string Title { get { return title; } set { title = value; RaisePropertyChanged(() => Title); } } } }
using System.Windows.Media; using ThinkGeo.MapSuite.Core; namespace ThinkGeo.MapSuite.USDemographicMap { public class GeoColorViewModel { private string colorName; private SolidColorBrush colorBrush; private GeoColor geoColor; public GeoColorViewModel() : this(GeoColor.StandardColors.Transparent, "Transparent") { } public GeoColorViewModel(GeoColor color, string colorName) { ColorBrush = new SolidColorBrush(Color.FromArgb(color.AlphaComponent, color.RedComponent, color.GreenComponent, color.BlueComponent)); ColorName = colorName; GeoColor = color; } public string ColorName { get { return colorName; } set { colorName = value; } } public SolidColorBrush ColorBrush { get { return colorBrush; } set { colorBrush = value; } } public GeoColor GeoColor { get { return geoColor; } set { geoColor = value; } } } }
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; using System.Linq; using System.Reflection; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Xml.Linq; using ThinkGeo.MapSuite.Core; using ThinkGeo.MapSuite.WpfDesktopEdition; namespace ThinkGeo.MapSuite.USDemographicMap { public class MainWindowViewModel : ViewModelBase { private string displayColorText; private double coordinateX; private double coordinateY; private ToolTip toolTip; private Visibility dotDensityVisibility; private Visibility valueCircleVisibility; private Visibility thematicVisibility; private ObservableCollection<DataCategoryViewModel> categoryList; private ObservableCollection<GeoColorViewModel> geoColorList; private ObservableCollection<ColorWheelDirection> colorWheelDirections; private GeoColorViewModel selectedColorItem; private GeoColorViewModel selectedEndColorItem; private DataCategoryViewModel selectedCategory; private ValueCircleDemographicStyleBuilder valueCircleStyleBuilder; private DotDensityDemographicStyleBuilder dotDensityStyleBuilder; private ThematicDemographicStyleBuilder thematicStyleBuilder; private PieChartDemographicStyleBuilder pieStyleBuilder; private DemographicStyleBuilder currentStyleBuilder; private MapModel mapModel; public MainWindowViewModel(MapModel mapModel) { this.mapModel = mapModel; InitializeProperties(); InitializetionDataCategories(); InitializeGeoSimpleColorsList(); InitializeEvents(mapModel); UpdateUIControls(ThematicDemographicStyle); SelectedCategory = CategoryList[0]; CurrentStyleBuilder.SelectedColumns.Add(SelectedCategory.Columns[0].ColumnName); mapModel.LegendTitle = SelectedCategory.Columns[0].LegendTitle; } public Visibility DotDensityVisibility { get { return dotDensityVisibility; } set { dotDensityVisibility = value; RaisePropertyChanged(() => DotDensityVisibility); } } public Visibility ValueCircleVisibility { get { return valueCircleVisibility; } set { valueCircleVisibility = value; RaisePropertyChanged(() => ValueCircleVisibility); } } public Visibility ThematicVisibility { get { return thematicVisibility; } set { thematicVisibility = value; RaisePropertyChanged(() => ThematicVisibility); } } public string DisplayColorText { get { return displayColorText; } set { displayColorText = value; RaisePropertyChanged(() => DisplayColorText); } } public ObservableCollection<DataCategoryViewModel> CategoryList { get { return categoryList; } } public ObservableCollection<ColorWheelDirection> ColorWheelDirections { get { return colorWheelDirections; } } public DotDensityDemographicStyleBuilder DotDensityDemographicStyle { get { return dotDensityStyleBuilder; } } public ObservableCollection<GeoColorViewModel> GeoColorList { get { return geoColorList; } } public PieChartDemographicStyleBuilder PieDemographicStyle { get { return pieStyleBuilder; } } public GeoColorViewModel SelectedColorItem { get { return selectedColorItem; } set { selectedColorItem = value; RaisePropertyChanged(() => SelectedColorItem); if (CurrentStyleBuilder != null && CurrentStyleBuilder.Color != selectedColorItem.GeoColor) { CurrentStyleBuilder.Color = selectedColorItem.GeoColor; UpdateMap(); } } } public DataCategoryViewModel SelectedCategory { get { return selectedCategory; } set { selectedCategory = value; RaisePropertyChanged(() => SelectedCategory); } } public ColorWheelDirection SelectedColorWheelDirection { get { return thematicStyleBuilder.ColorWheelDirection; } set { thematicStyleBuilder.ColorWheelDirection = value; RaisePropertyChanged(() => SelectedColorWheelDirection); if (CurrentStyleBuilder != null) { UpdateMap(); } } } public GeoColorViewModel SelectedEndColorItem { get { return selectedEndColorItem; } set { selectedEndColorItem = value; RaisePropertyChanged(() => SelectedEndColorItem); if (ThematicDemographicStyle != null && ThematicDemographicStyle.EndColor != selectedEndColorItem.GeoColor) { ThematicDemographicStyle.EndColor = selectedEndColorItem.GeoColor; UpdateMap(); } } } public ThematicDemographicStyleBuilder ThematicDemographicStyle { get { return thematicStyleBuilder; } } public ValueCircleDemographicStyleBuilder ValueCircleDemographicStyle { get { return valueCircleStyleBuilder; } } public DemographicStyleBuilder CurrentStyleBuilder { get { return currentStyleBuilder; } } public double CoordinateX { get { return coordinateX; } set { coordinateX = value; RaisePropertyChanged(() => CoordinateX); } } public double CoordinateY { get { return coordinateY; } set { coordinateY = value; RaisePropertyChanged(() => CoordinateY); } } public void CreatePieDemographicStyle() { PieDemographicStyle.SelectedColumnAliases.Clear(); PieDemographicStyle.SelectedColumns.Clear(); foreach (var item in SelectedCategory.Columns) { item.CheckBoxVisiblity = Visibility.Visible; } foreach (var item in SelectedCategory.Columns.Where(d => d.IsSelected)) { PieDemographicStyle.SelectedColumns.Add(item.ColumnName); PieDemographicStyle.SelectedColumnAliases.Add(item.Alias); } UpdateUIControls(PieDemographicStyle); mapModel.LegendTitle = SelectedCategory.Title; } public void UpdateMap() { Collection<ThinkGeo.MapSuite.Core.Style> activeStyles = CurrentStyleBuilder.GetStyles(mapModel.DefaultFeatureLayer.FeatureSource); mapModel.DefaultFeatureLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Clear(); foreach (var activeStyle in activeStyles) { mapModel.DefaultFeatureLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(activeStyle); } mapModel.DefaultFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; UpdateLegend(CurrentStyleBuilder, mapModel.LegendAdornmentLayer); mapModel.MapControl.Refresh(new Overlay[] { mapModel.DemographicLayerOverlay, mapModel.MapControl.AdornmentOverlay }); } public void UpdateUIControls(DemographicStyleBuilder activeSettingViewModel) { GeoColor[] colors = GeoColorList.Select(c => c.GeoColor).ToArray(); for (int i = 0; i < colors.Length; i++) { if (colors[i].Equals(activeSettingViewModel.Color)) { currentStyleBuilder = activeSettingViewModel; SelectedColorItem = GeoColorList[i]; break; } } ThematicDemographicStyleBuilder thematicDemographicStyleBuilder = activeSettingViewModel as ThematicDemographicStyleBuilder; if (thematicDemographicStyleBuilder != null) { GeoColor styleColor = thematicDemographicStyleBuilder.EndColor; for (int i = 0; i < colors.Length; i++) { if (colors[i].Equals(styleColor)) { currentStyleBuilder = activeSettingViewModel; SelectedEndColorItem = GeoColorList[i]; break; } } } } private void InitializeProperties() { toolTip = new ToolTip(); DotDensityVisibility = Visibility.Collapsed; ValueCircleVisibility = Visibility.Collapsed; DisplayColorText = "Display Color:"; colorWheelDirections = new ObservableCollection<ColorWheelDirection>(); colorWheelDirections.Add(ColorWheelDirection.Clockwise); colorWheelDirections.Add(ColorWheelDirection.CounterClockwise); categoryList = new ObservableCollection<DataCategoryViewModel>(); valueCircleStyleBuilder = new ValueCircleDemographicStyleBuilder(); dotDensityStyleBuilder = new DotDensityDemographicStyleBuilder(); pieStyleBuilder = new PieChartDemographicStyleBuilder(); thematicStyleBuilder = new ThematicDemographicStyleBuilder(); } private void InitializeEvents(MapModel mapModel) { mapModel.MapControl.MapTools.MouseCoordinate.CustomFormatted += MouseCoordinate_CustomFormatted; mapModel.MapControl.MouseMove += WpfMap_MouseMove; } private void WpfMap_MouseMove(object sender, MouseEventArgs e) { toolTip.IsOpen = false; mapModel.HighlightOverlay.HighlightFeature = null; if (!mapModel.HighlightOverlay.IsPanningMap) { Point screenLocation = e.GetPosition(mapModel.MapControl); PointShape worldLoction = ExtentHelper.ToWorldCoordinate(mapModel.MapControl.CurrentExtent, new ScreenPointF((float)screenLocation.X, (float)screenLocation.Y), (float)mapModel.MapControl.ActualWidth, (float)mapModel.MapControl.ActualHeight); // Here we get tootip for the highlighted feature. if (worldLoction.X > -180 && worldLoction.X < 180 && worldLoction.Y > -90 && worldLoction.Y < 90) { mapModel.DefaultFeatureLayer.Open(); List<string> columnNames = mapModel.DefaultFeatureLayer.FeatureSource.GetColumns().Select(x => x.ColumnName).ToList(); Collection<Feature> nearestFeatures = mapModel.DefaultFeatureLayer.QueryTools.GetFeaturesNearestTo(worldLoction, mapModel.MapControl.MapUnit, 1, columnNames, 1, DistanceUnit.Meter); if (nearestFeatures.Count > 0) { var highlightedFeature = nearestFeatures[0]; mapModel.HighlightOverlay.HighlightFeature = highlightedFeature; mapModel.HighlightOverlay.Refresh(); var content = GetToolTip(highlightedFeature); toolTip.Content = content; toolTip.IsOpen = true; } } } mapModel.HighlightOverlay.Refresh(); } private void MouseCoordinate_CustomFormatted(object sender, CustomFormattedMouseCoordinateMapToolEventArgs e) { CoordinateX = e.WorldCoordinate.X; CoordinateY = e.WorldCoordinate.Y; } private void InitializeGeoSimpleColorsList() { geoColorList = new ObservableCollection<GeoColorViewModel>(); PropertyInfo[] propertyInfos = GeoColor.SimpleColors.GetType().GetProperties(); foreach (PropertyInfo propertyInfo in propertyInfos) { object value = propertyInfo.GetValue(GeoColor.SimpleColors, null); string name = propertyInfo.Name; if (name.ToUpperInvariant() == "TRANSPARENT") { continue; } if (value.GetType() == typeof(GeoColor)) { GeoColorViewModel colorItem = new GeoColorViewModel((GeoColor)value, name); geoColorList.Add(colorItem); } } } // Here we load all the nodes on the left from xml file. private void InitializetionDataCategories() { var xDoc = XDocument.Load(MapSuiteSampleHelper.GetValueFromConfiguration("CategoryFilePath")); var elements = from category in xDoc.Element("DemographicMap").Elements("Category") select category; foreach (var element in elements) { DataCategoryViewModel category = null; string title = element.Attribute("name").Value; category = title != "Custom Data" ? new DataCategoryViewModel() : new CustomDataCategoryViewModel(); category.Title = title; category.CategoryImage = new BitmapImage(new Uri(string.Format(CultureInfo.InvariantCulture, "{0}{1}", "pack://application:,,,/MapSuiteUSDemographicMap;component/", element.Attribute("icon").Value), UriKind.RelativeOrAbsolute)); foreach (var item in element.Elements("item")) { ColumnViewModel categoryItem = new ColumnViewModel(); categoryItem.Parent = category; categoryItem.ColumnName = item.Element("columnName").Value; categoryItem.Alias = item.Element("alias").Value; categoryItem.LegendTitle = item.Element("legendTitle").Value; category.Columns.Add(categoryItem); } category.CanUsePieView = category.Columns.Count >= 2; CategoryList.Add(category); } } public StackPanel GetToolTip(Feature feature) { StackPanel popupPanel = new StackPanel(); popupPanel.Margin = new Thickness(5); if (mapModel.DefaultFeatureLayer == mapModel.CensusStateFeatureLayer) { TextBlock stateName = new TextBlock(); stateName.FontWeight = FontWeights.Bold; stateName.FontFamily = new FontFamily("Segoe UI"); stateName.Text = feature.ColumnValues["NAME"]; stateName.FontSize = 14; stateName.Margin = new Thickness(0, 0, 0, 10); popupPanel.Children.Add(stateName); popupPanel.Children.Add(new Separator() { Margin = new Thickness(0, 0, 0, 10) }); } foreach (var column in CurrentStyleBuilder.SelectedColumns) { if (feature.ColumnValues.ContainsKey(column)) { TextBlock columnText = new TextBlock(); columnText.FontFamily = new FontFamily("Segoe UI"); columnText.Text = TextFormatter.GetFormatedString(column, double.Parse(feature.ColumnValues[column])); columnText.FontSize = 12; columnText.Margin = new Thickness(0, 0, 0, 3); popupPanel.Children.Add(columnText); } } return popupPanel; } private void UpdateLegend(DemographicStyleBuilder styleBuilder, LegendAdornmentLayer legendAdornmentLayer) { legendAdornmentLayer.LegendItems.Clear(); if (styleBuilder is ThematicDemographicStyleBuilder) { AddThematicLegendItems(legendAdornmentLayer); } else if (styleBuilder is DotDensityDemographicStyleBuilder) { AddDotDensityLegendItems(legendAdornmentLayer); } else if (styleBuilder is ValueCircleDemographicStyleBuilder) { AddValueCircleLegendItems(legendAdornmentLayer); } else if (styleBuilder is PieChartDemographicStyleBuilder) { AddPieGraphLegendItems(legendAdornmentLayer); } legendAdornmentLayer.ContentResizeMode = LegendContentResizeMode.Fixed; legendAdornmentLayer.Height = GetLegendHeight(legendAdornmentLayer); legendAdornmentLayer.Width = GetLegendWidth(legendAdornmentLayer); } private float GetLegendWidth(LegendAdornmentLayer legendAdornmentLayer) { GdiPlusGeoCanvas gdiPlusGeoCanvas = new GdiPlusGeoCanvas(); LegendItem title = legendAdornmentLayer.Title; float width = gdiPlusGeoCanvas.MeasureText(title.TextStyle.TextColumnName, new GeoFont("Segoe UI", 12)).Width + title.ImageWidth + title.ImageRightPadding + title.ImageLeftPadding + title.TextRightPadding + title.TextLeftPadding + title.LeftPadding + title.RightPadding; foreach (LegendItem legendItem in legendAdornmentLayer.LegendItems) { float legendItemWidth = gdiPlusGeoCanvas.MeasureText(legendItem.TextStyle.TextColumnName, new GeoFont("Segoe UI", 10)).Width + legendItem.ImageWidth + legendItem.ImageRightPadding + legendItem.ImageLeftPadding + legendItem.TextRightPadding + legendItem.TextLeftPadding + legendItem.LeftPadding + legendItem.RightPadding; if (width < legendItemWidth) { width = legendItemWidth; } } return width; } private float GetLegendHeight(LegendAdornmentLayer legendAdornmentLayer) { GdiPlusGeoCanvas gdiPlusGeoCanvas = new GdiPlusGeoCanvas(); LegendItem title = legendAdornmentLayer.Title; float titleMeasuredHeight = gdiPlusGeoCanvas.MeasureText(title.TextStyle.TextColumnName, new GeoFont("Segoe UI", 12)).Height; float legendHeight = new[] { titleMeasuredHeight, title.ImageHeight, title.Height }.Max(); float height = legendHeight + Math.Max(title.ImageTopPadding, title.TextTopPadding) + title.TopPadding + Math.Max(title.ImageBottomPadding, title.TextBottomPadding) + title.BottomPadding; foreach (LegendItem legendItem in legendAdornmentLayer.LegendItems) { float itemLegendHeight = Math.Max(gdiPlusGeoCanvas.MeasureText(legendItem.TextStyle.TextColumnName, new GeoFont("Segoe UI", 10)).Height, legendItem.ImageHeight); float itemHeight = itemLegendHeight + Math.Max(legendItem.ImageTopPadding, legendItem.TextTopPadding) + legendItem.TopPadding + Math.Max(legendItem.ImageBottomPadding, legendItem.TextBottomPadding) + legendItem.BottomPadding; height += itemHeight; } return height; } private void AddPieGraphLegendItems(LegendAdornmentLayer legendAdornmentLayer) { PieZedGraphStyle zedGraphStyle = (PieZedGraphStyle)CurrentStyleBuilder.GetStyles(mapModel.DefaultFeatureLayer.FeatureSource)[0]; foreach (KeyValuePair<string, GeoColor> item in zedGraphStyle.PieSlices) { LegendItem legendItem = new LegendItem(); legendItem.ImageWidth = 20; legendItem.TextRightPadding = 5; legendItem.RightPadding = 5; legendItem.ImageStyle = new AreaStyle(new GeoSolidBrush(item.Value)); legendItem.TextStyle = new TextStyle(item.Key, new GeoFont("Segoe UI", 10), new GeoSolidBrush(GeoColor.SimpleColors.Black)); legendAdornmentLayer.LegendItems.Add(legendItem); } } private void AddValueCircleLegendItems(LegendAdornmentLayer legendAdornmentLayer) { ValueCircleStyle valueCircleStyle = (ValueCircleStyle)CurrentStyleBuilder.GetStyles(mapModel.DefaultFeatureLayer.FeatureSource)[0]; // Here we generate 4 legend items, with the area of 160, 320, 640 and 1280 square pixels seperately. int[] circleAreas = new int[] { 160, 320, 640, 1280 }; foreach (int circleArea in circleAreas) { LegendItem legendItem = new LegendItem(); double radius = Math.Sqrt(circleArea / Math.PI); legendItem.ImageStyle = new PointStyle(PointSymbolType.Circle, new GeoSolidBrush(valueCircleStyle.InnerColor), new GeoPen(new GeoSolidBrush(valueCircleStyle.OuterColor)), (int)(radius * 2)); AreaStyle maskStyle = new AreaStyle(new GeoPen(GeoColor.StandardColors.LightGray, 1), new GeoSolidBrush(GeoColor.SimpleColors.Transparent)); legendItem.ImageMask = maskStyle; legendItem.ImageWidth = 48; legendItem.TextTopPadding = 16; legendItem.TextRightPadding = 5; legendItem.BottomPadding = 16; legendItem.TopPadding = 16; legendItem.RightPadding = 5; double drawingRadius = circleArea / valueCircleStyle.DrawingRadiusRatio * valueCircleStyle.BasedScale / valueCircleStyle.DefaultZoomLevel.Scale; double ratio = (valueCircleStyle.MaxValidValue - valueCircleStyle.MinValidValue) / (valueCircleStyle.MaxCircleAreaInDefaultZoomLevel - valueCircleStyle.MinCircleAreaInDefaultZoomLevel); double resultValue = (drawingRadius - valueCircleStyle.MinCircleAreaInDefaultZoomLevel) * ratio + valueCircleStyle.MinValidValue; string text = TextFormatter.GetFormatedStringForLegendItem(valueCircleStyle.ColumnName, resultValue); legendItem.TextStyle = new TextStyle(text, new GeoFont("Segoe UI", 10), new GeoSolidBrush(GeoColor.SimpleColors.Black)); legendAdornmentLayer.LegendItems.Add(legendItem); } } private void AddDotDensityLegendItems(LegendAdornmentLayer legendAdornmentLayer) { CustomDotDensityStyle dotDensityStyle = (CustomDotDensityStyle)CurrentStyleBuilder.GetStyles(mapModel.DefaultFeatureLayer.FeatureSource)[0]; // Here we generate 4 legend items, for 5, 10, 20 and 50 points seperately. int[] pointCounts = new int[] { 5, 10, 20, 50 }; foreach (int pointCount in pointCounts) { LegendItem legendItem = new LegendItem(); legendItem.ImageMask = new AreaStyle(new GeoPen(GeoColor.StandardColors.LightGray, 1), new GeoSolidBrush(GeoColor.SimpleColors.Transparent)); legendItem.ImageWidth = 48; legendItem.TextTopPadding = 16; legendItem.TextRightPadding = 5; legendItem.BottomPadding = 16; legendItem.TopPadding = 16; legendItem.RightPadding = 5; CustomDotDensityStyle legendDotDensityStyle = (CustomDotDensityStyle)dotDensityStyle.CloneDeep(); legendDotDensityStyle.DrawingPointsNumber = pointCount; legendItem.ImageStyle = legendDotDensityStyle; string text = string.Format(CultureInfo.InvariantCulture, "{0:0.####}", TextFormatter.GetFormatedStringForLegendItem(dotDensityStyle.ColumnName, (pointCount / dotDensityStyle.PointToValueRatio))); legendItem.TextStyle = new TextStyle(text, new GeoFont("Segoe UI", 10), new GeoSolidBrush(GeoColor.SimpleColors.Black)); legendAdornmentLayer.LegendItems.Add(legendItem); } } private void AddThematicLegendItems(LegendAdornmentLayer legendAdornmentLayer) { ClassBreakStyle thematicStyle = (ClassBreakStyle)CurrentStyleBuilder.GetStyles(mapModel.DefaultFeatureLayer.FeatureSource)[0]; for (int i = 0; i < thematicStyle.ClassBreaks.Count; i++) { LegendItem legendItem = new LegendItem(); if (i < thematicStyle.ClassBreaks.Count) { legendItem.ImageStyle = thematicStyle.ClassBreaks[i].DefaultAreaStyle; legendItem.ImageWidth = 20; legendItem.TextRightPadding = 5; legendItem.RightPadding = 5; string text = string.Empty; if (i != thematicStyle.ClassBreaks.Count - 1) { text = string.Format("{0:#,0.####} ~ {1:#,0.####}", TextFormatter.GetFormatedStringForLegendItem(thematicStyle.ColumnName, thematicStyle.ClassBreaks[i].Value), TextFormatter.GetFormatedStringForLegendItem(thematicStyle.ColumnName, thematicStyle.ClassBreaks[i|+ 1].Value)); } else { text = string.Format("> {0:#,0.####}", TextFormatter.GetFormatedStringForLegendItem(thematicStyle.ColumnName, thematicStyle.ClassBreaks[i].Value)); } legendItem.TextStyle = new TextStyle(text, new GeoFont("Segoe UI", 10), new GeoSolidBrush(GeoColor.SimpleColors.Black)); } legendAdornmentLayer.LegendItems.Add(legendItem); } } } }
using System; using System.Collections.ObjectModel; using ThinkGeo.MapSuite.Core; namespace ThinkGeo.MapSuite.USDemographicMap { // We custom this DotDensity Style to enhance its drawing on the legend. [Serializable] class CustomDotDensityStyle : DotDensityStyle { private int drawingPointsNumber; public CustomDotDensityStyle() : base() { } public int DrawingPointsNumber { get { return drawingPointsNumber; } set { drawingPointsNumber = value; } } protected override void DrawSampleCore(GeoCanvas canvas, DrawingRectangleF drawingExtent) { base.DrawSampleCore(canvas, drawingExtent); PointShape upperLeftPoint = ExtentHelper.ToWorldCoordinate(canvas.CurrentWorldExtent, drawingExtent.CenterX - drawingExtent.Width / 2, drawingExtent.CenterY - drawingExtent.Height / 2, canvas.Width, canvas.Height); PointShape lowerRightPoint = ExtentHelper.ToWorldCoordinate(canvas.CurrentWorldExtent, drawingExtent.CenterX + drawingExtent.Width / 2, drawingExtent.CenterY + drawingExtent.Height / 2, canvas.Width, canvas.Height); RectangleShape rectangle = new RectangleShape(upperLeftPoint, lowerRightPoint); rectangle.ScaleDown(10); // Here draw the points on Legend Image Random random = new Random(DateTime.Now.Millisecond); Collection<BaseShape> drawingPoints = new Collection<BaseShape>(); for (int i = 0; i < DrawingPointsNumber; i++) { double x = rectangle.LowerLeftPoint.X + random.NextDouble() * (rectangle.Width); double y = rectangle.LowerLeftPoint.Y + random.NextDouble() * (rectangle.Height); drawingPoints.Add(new PointShape(x, y)); } TextStyle textStyle = new TextStyle(DrawingPointsNumber.ToString(), new GeoFont("Arial", 20, DrawingFontStyles.Bold), new GeoSolidBrush(GeoColor.FromArgb(180, GeoColor.FromHtml("#d3d3d3")))); textStyle.DrawSample(canvas, drawingExtent); CustomPointStyle.Draw(drawingPoints, canvas, new Collection<SimpleCandidate>(), new Collection<SimpleCandidate>()); } } }
using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using ThinkGeo.MapSuite.Core; namespace ThinkGeo.MapSuite.USDemographicMap { // We have the StyleBuilder to generate different styles public abstract class DemographicStyleBuilder { private int opacity; private GeoColor color; private Collection<string> selectedColumns; protected DemographicStyleBuilder() : this(new Collection<string>()) { } protected DemographicStyleBuilder(IEnumerable<string> selectedColumns) { this.Opacity = 100; this.color = GeoColor.FromHtml("#F1F369"); this.selectedColumns = new Collection<string>(selectedColumns.ToList()); } // The generated style would based on the columns we selected here. // Multiple columns are required For PieChart style, only one column is needed for other styles in this sample. public Collection<string> SelectedColumns { get { return selectedColumns; } } public GeoColor Color { get { return color; } set { color = value; } } public int Opacity { get { return opacity; } protected set { opacity = value; } } public Collection<Style> GetStyles(FeatureSource featureSource) { return GetStylesCore(featureSource); } protected abstract Collection<Style> GetStylesCore(FeatureSource featureSource); } }
using System.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; using ThinkGeo.MapSuite.Core; namespace ThinkGeo.MapSuite.USDemographicMap { public class DotDensityDemographicStyleBuilder : DemographicStyleBuilder { private double dotDensityValue; public DotDensityDemographicStyleBuilder() : this(new string[] { }) { } public DotDensityDemographicStyleBuilder(IEnumerable<string> selectedColumns) : base(selectedColumns) { Opacity = 255; DotDensityValue = 50; Color = GeoColor.SimpleColors.DarkRed; } public double DotDensityValue { get { return dotDensityValue; } set { dotDensityValue = value; } } protected override Collection<Style> GetStylesCore(FeatureSource featureSource) { // here we generate CustomDotDensityStyle. double totalValue = 0; featureSource.Open(); int featureCount = featureSource.GetCount(); for (int i = 0; i < featureCount; i++) { Feature feature = featureSource.GetFeatureById((i + 1).ToString(CultureInfo.InvariantCulture), SelectedColumns); double columnValue; if (double.TryParse(feature.ColumnValues[SelectedColumns[0], out columnValue)) { totalValue += columnValue; } } featureSource.Close(); CustomDotDensityStyle dotDensityStyle = new CustomDotDensityStyle(); dotDensityStyle.ColumnName = SelectedColumns[0]; dotDensityStyle.PointToValueRatio = DotDensityValue / (totalValue / featureCount); dotDensityStyle.CustomPointStyle = PointStyles.CreateSimpleCircleStyle(GeoColor.FromArgb(Opacity, Color), 4); return new Collection<Style>() { dotDensityStyle }; } } }
using System.Collections.Generic; using System.Collections.ObjectModel; using System.Drawing; using ThinkGeo.MapSuite.Core; using ZedGraph; namespace ThinkGeo.MapSuite.USDemographicMap { public class PieChartDemographicStyleBuilder : DemographicStyleBuilder { private Collection<string> selectedColumnAliases; private Collection<GeoColor> pieColors; public PieChartDemographicStyleBuilder() : this(new string[] { }) { } public PieChartDemographicStyleBuilder(IEnumerable<string> selectedColumns) : base(selectedColumns) { Opacity = 200; Color = GeoColor.SimpleColors.LightBlue; selectedColumnAliases = new Collection<string>(); } public Collection<string> SelectedColumnAliases { get { return selectedColumnAliases; } } protected override Collection<Style> GetStylesCore(FeatureSource featureSource) { // here we generated the PieZedGraphStyle. PieZedGraphStyle zedGraphStyle = new PieZedGraphStyle(); zedGraphStyle.ZedGraphDrawing += ZedGraphStyle_ZedGraphDrawing; pieColors = GeoColor.GetColorsInQualityFamily(GeoColor.FromArgb(Opacity, Color), SelectedColumns.Count); for (int i = 0; i < SelectedColumns.Count; i++) { zedGraphStyle.RequiredColumnNames.Add(SelectedColumns[i]); zedGraphStyle.PieSlices.Add(SelectedColumnAliases[i], pieColors[i]); } return new Collection<Style>(){zedGraphStyle}; } private void ZedGraphStyle_ZedGraphDrawing(object sender, ZedGraphDrawingEventArgs e) { ZedGraphControl zedGraph = new ZedGraphControl(); zedGraph.Size = new Size(100, 100); zedGraph.GraphPane.Fill.Type = FillType.None; zedGraph.GraphPane.Chart.Fill.Type = FillType.None; zedGraph.GraphPane.Border.IsVisible = false; zedGraph.GraphPane.Chart.Border.IsVisible = false; zedGraph.GraphPane.XAxis.IsVisible = false; zedGraph.GraphPane.YAxis.IsVisible = false; zedGraph.GraphPane.Legend.IsVisible = false; zedGraph.GraphPane.Title.IsVisible = false; for (int i = 0; i < SelectedColumns.Count; i++) { double value = 0; if (!double.TryParse(e.Feature.ColumnValues[SelectedColumns[i], out value)) { zedGraph.Dispose(); return; } Color color = System.Drawing.Color.FromArgb(pieColors[i].AlphaComponent, pieColors[i].RedComponent, pieColors[i].GreenComponent, pieColors[i].BlueComponent); PieItem pieItem = zedGraph.GraphPane.AddPieSlice(value, color, 0.08, ""); pieItem.LabelDetail.IsVisible = false; } zedGraph.AxisChange(); e.Bitmap = zedGraph.GraphPane.GetImage(); zedGraph.Dispose(); } } }
using System.Collections.Generic; using ThinkGeo.MapSuite.Core; namespace ThinkGeo.MapSuite.USDemographicMap { // We custom this class just make it a bit easier to use. public class PieZedGraphStyle : ZedGraphStyle { private Dictionary<string, GeoColor> pieSlices; public PieZedGraphStyle() { pieSlices = new Dictionary<string, GeoColor>(); } public Dictionary<string, GeoColor> PieSlices { get { return pieSlices; } } } }
using System.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; using System.Linq; using ThinkGeo.MapSuite.Core; namespace ThinkGeo.MapSuite.USDemographicMap { public class ThematicDemographicStyleBuilder : DemographicStyleBuilder { private int classBreakCount; private GeoColor endColor; private ColorWheelDirection colorWheelDirection; public ThematicDemographicStyleBuilder() : this(new string[] { }) { } public ThematicDemographicStyleBuilder(IEnumerable<string> selectedColumns) : base(selectedColumns) { Opacity = 200; ClassBreakCount = 10; Color = GeoColor.SimpleColors.LightBlue; EndColor = GeoColor.SimpleColors.LightRed; ColorWheelDirection = ColorWheelDirection.CounterClockwise; } public int ClassBreakCount { get { return classBreakCount; } set { classBreakCount = value; } } public ColorWheelDirection ColorWheelDirection { get { return colorWheelDirection; } set { colorWheelDirection = value; } } public GeoColor StartColor { get { return Color; } set { Color = value; } } public GeoColor EndColor { get { return endColor; } set { endColor = value; } } protected override Collection<Style> GetStylesCore(FeatureSource featureSource) { // here we generated a class break style and a text style. Collection<GeoColor> familyColors = GeoColor.GetColorsInQualityFamily(Color, EndColor, classBreakCount, ColorWheelDirection); featureSource.Open(); int featureCount = featureSource.GetCount(); double[] values = new double[featureCount]; for (int i = 0; i < featureCount; i++) { Feature feature = featureSource.GetFeatureById((i + 1).ToString(CultureInfo.InvariantCulture), SelectedColumns); double columnValue; if (double.TryParse(feature.ColumnValues[SelectedColumns[0], out columnValue)) { values[i] = columnValue; } } featureSource.Close(); ClassBreakStyle classBreakStyle = new ClassBreakStyle(SelectedColumns[0]) { BreakValueInclusion = BreakValueInclusion.IncludeValue }; double[] classBreakValues = GetClusterClassBreaks(values, ClassBreakCount - 1); for (int i = 0; i < classBreakValues.Length; i++) { ClassBreak classBreak = new ClassBreak(classBreakValues[i], AreaStyles.CreateSimpleAreaStyle(new GeoColor(this.Opacity, familyColors[i]), GeoColor.FromHtml("#f05133"), 1)); classBreakStyle.ClassBreaks.Add(classBreak); } return new Collection<Style>() { classBreakStyle, TextStyles.Country1("NAME") }; } private double[] GetClusterClassBreaks(double[] values, int count) { var result = new List<double>(); var orderedValues = values.OrderBy(v => v).ToArray(); var min = orderedValues[0]; var max = orderedValues[orderedValues.Length|- 1]; var classesCount = (int)(orderedValues.Length / count); var breakValue = min; for (var i = 1; i < count; i++) { breakValue = orderedValues[i|* classesCount]; if (!result.Contains(breakValue)) { result.Add(breakValue); } } result.Insert(0, 0); return result.ToArray(); } } }
using System.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; using ThinkGeo.MapSuite.Core; namespace ThinkGeo.MapSuite.USDemographicMap { public class ValueCircleDemographicStyleBuilder : DemographicStyleBuilder { private double radiusRatio; public ValueCircleDemographicStyleBuilder() : this(new string[] { }) { } public ValueCircleDemographicStyleBuilder(IEnumerable<string> selectedColumns) : base(selectedColumns) { radiusRatio = 1; Color = GeoColor.SimpleColors.BrightOrange; Opacity = 160; } public double RadiusRatio { get { return radiusRatio; } set { radiusRatio = value; } } protected override Collection<Style> GetStylesCore(FeatureSource featureSource) { // here we generate a ValueCircle Style. double minValue = double.MaxValue; double maxValue = double.MinValue; featureSource.Open(); for (int i = 0; i < featureSource.GetCount(); i++) { Feature feature = featureSource.GetFeatureById((i + 1).ToString(CultureInfo.InvariantCulture), SelectedColumns); double columnValue; if (double.TryParse(feature.ColumnValues[SelectedColumns[0], out columnValue)) { if (columnValue < minValue) { minValue = columnValue; } else if (columnValue > maxValue) { maxValue = columnValue; } } } featureSource.Close(); ValueCircleStyle valueCircleStyle = new ValueCircleStyle(); valueCircleStyle.ColumnName = SelectedColumns[0]; valueCircleStyle.DrawingRadiusRatio = radiusRatio; valueCircleStyle.MinValidValue = minValue; valueCircleStyle.MaxValidValue = maxValue; valueCircleStyle.MinCircleAreaInDefaultZoomLevel = 80; valueCircleStyle.MaxCircleAreaInDefaultZoomLevel = 10000; valueCircleStyle.InnerColor = GeoColor.FromArgb(this.Opacity, Color); valueCircleStyle.OuterColor = GeoColor.SimpleColors.White; return new Collection<Style>(){valueCircleStyle}; } } }
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using ThinkGeo.MapSuite.Core; namespace ThinkGeo.MapSuite.USDemographicMap { // This custom style is for displaying circles with different sizes based on the value. public class ValueCircleStyle : Style { private string columnName; private double baseScale; private double minValidValue; private double maxValidValue; private double drawingRadiusRatio; private double maxCircleRadiusInDefaultZoomLevel; private double minCircleRadiusInDefaultZoomLevel; private GeoColor innerColor; private GeoColor outerColor; private ZoomLevel defaultZoomLevel; public ValueCircleStyle() : base() { ZoomLevelSet zoomLevelSet = new ZoomLevelSet(); defaultZoomLevel = zoomLevelSet.ZoomLevel04; baseScale = zoomLevelSet.ZoomLevel05.Scale; drawingRadiusRatio = 1; outerColor = GeoColor.FromArgb(255, 10, 20, 255); innerColor = GeoColor.FromArgb(100, 10, 20, 255); minCircleRadiusInDefaultZoomLevel = 10; maxCircleRadiusInDefaultZoomLevel = 100; } public string ColumnName { get { return columnName; } set { columnName = value; } } public ZoomLevel DefaultZoomLevel { get { return defaultZoomLevel; } set { defaultZoomLevel = value; } } public double DrawingRadiusRatio { get { return drawingRadiusRatio; } set { drawingRadiusRatio = value; } } public GeoColor InnerColor { get { return innerColor; } set { innerColor = value; } } // The data might be dramatically different but we don't want any circle be super large // on the map, so here we have this property to identify the max circle we can have on map. public double MaxCircleAreaInDefaultZoomLevel { get { return maxCircleRadiusInDefaultZoomLevel; } set { maxCircleRadiusInDefaultZoomLevel = value; } } public double MaxValidValue { get { return maxValidValue; } set { maxValidValue = value; } } // The data might be dramatically different but we don't want any circle be super tiny // on the map, so here we have this property to identify the min circle we can have on map. public double MinCircleAreaInDefaultZoomLevel { get { return minCircleRadiusInDefaultZoomLevel; } set { minCircleRadiusInDefaultZoomLevel = value; } } public double MinValidValue { get { return minValidValue; } set { minValidValue = value; } } public GeoColor OuterColor { get { return outerColor; } set { outerColor = value; } } public double BasedScale { get { return baseScale; } } protected override void DrawCore(IEnumerable<Feature> features, GeoCanvas canvas, Collection<SimpleCandidate> labelsInThisLayer, Collection<SimpleCandidate> labelsInAllLayers) { double ratio = (maxValidValue - minValidValue) / (maxCircleRadiusInDefaultZoomLevel - minCircleRadiusInDefaultZoomLevel); // here we calculate the size of each circle based on every feature's value. foreach (Feature feature in features) { double value = 0; if (!double.TryParse(feature.ColumnValues[columnName], out value)) { continue; } if (value > maxValidValue || value < minValidValue) { continue; } double drawingDefaultCircleArea = (value - minValidValue) / ratio + minCircleRadiusInDefaultZoomLevel; double graphArea = drawingDefaultCircleArea * defaultZoomLevel.Scale / baseScale * drawingRadiusRatio; double graphHeght = Math.Sqrt(graphArea / Math.PI); PointShape center = feature.GetShape().GetCenterPoint(); canvas.DrawEllipse(center, (float)(graphHeght * 2), (float)(graphHeght * 2), new GeoPen(outerColor, 1), new GeoSolidBrush(innerColor), DrawingLevel.LevelOne); } } protected override Collection<string> GetRequiredColumnNamesCore() { Collection<string> requiredFieldNames = new Collection<string>(); requiredFieldNames.Add(columnName); return requiredFieldNames; } } }