?WPF 實現柱形統計圖
WPF 實現柱形統計圖
作者:WPFDevelopersOrg
原文鏈接:? ?https://github.com/WPFDevelopersOrg/WPFDevelopers
框架使用大于等于
.NET40
;Visual Studio 2022
;項目使用 MIT 開源許可協議;
避免畫線發虛DrawingContext繪制Line的時候會發虛,以下方法可以避免;
var?d?=?Pen.Thickness?/?2;var?guidelines?=?new?GuidelineSet(new[]?{?d?},?new[]?{?d?});drawingContext.PushGuidelineSet(guidelines);或者調用SnapDrawingExtensions.DrawSnappedLinesBetweenPoints
1) BasicBarChart.cs 代碼如下;
using?System;
using?System.Collections.Generic;
using?System.Linq;
using?System.Windows;
using?System.Windows.Controls;
using?System.Windows.Media;namespace?WPFDevelopers.Controls
{public?class?BasicBarChart?:?Control{public?static?readonly?DependencyProperty?SeriesArrayProperty?=DependencyProperty.Register("SeriesArray",?typeof(IEnumerable<KeyValuePair<string,?double>>),typeof(BasicBarChart),?new?UIPropertyMetadata(SeriesArrayChanged));static?BasicBarChart(){DefaultStyleKeyProperty.OverrideMetadata(typeof(BasicBarChart),new?FrameworkPropertyMetadata(typeof(BasicBarChart)));}public?IEnumerable<KeyValuePair<string,?double>>?SeriesArray{get?=>?(IEnumerable<KeyValuePair<string,?double>>)GetValue(SeriesArrayProperty);set?=>?SetValue(SeriesArrayProperty,?value);}private?static?void?SeriesArrayChanged(DependencyObject?d,?DependencyPropertyChangedEventArgs?e){var?radarChart?=?d?as?BasicBarChart;if?(e.NewValue?!=?null)radarChart.InvalidateVisual();}protected?override?void?OnRender(DrawingContext?drawingContext){//base.OnRender(drawingContext);if?(SeriesArray?==?null?||?SeriesArray.Count()?==?0)return;SnapsToDevicePixels?=?true;UseLayoutRounding?=?true;var?brushConverter?=?new?BrushConverter();var?myPen?=?new?Pen{Thickness?=?1,Brush?=?(Brush)brushConverter.ConvertFromString("#6E7079")};myPen.Freeze();//var?d?=?myPen.Thickness?/?2;//var?guidelines?=?new?GuidelineSet(new[]?{?d?},?new[]?{?d?});//drawingContext.PushGuidelineSet(guidelines);var?h?=?ActualHeight?/?2?+?160;var?w?=?ActualWidth?/?2;var?startX?=?w?/?3;var?width?=?SeriesArray.Count()?*?120?+?startX;//drawingContext.DrawLine(myPen,?new?Point(startX,?h),?new?Point(width,?h));var?stratNum?=?0;drawingContext.DrawSnappedLinesBetweenPoints(myPen,?myPen.Thickness,?new?Point(startX,?h),new?Point(width,?h));var?formattedText?=?DrawingContextHelper.GetFormattedText(stratNum.ToString(),(Brush)brushConverter.ConvertFromString("#6E7079"),?FlowDirection.LeftToRight);drawingContext.DrawText(formattedText,new?Point(startX?-?formattedText.Width?*?2?-?10,?h?-?formattedText.Height?/?2));var?x?=?startX;//var?y?=?h?+?d;var?y?=?h?+?myPen.Thickness;var?points?=?new?List<Point>();var?rectBrush?=?new?SolidColorBrush((Color)ColorConverter.ConvertFromString("#5470C6"));for?(var?i?=?0;?i?<?SeriesArray.Count()?+?1;?i++){//drawingContext.DrawLine(myPen,?new?Point(x,?y),?new?Point(x,?y?+?4));points.Add(new?Point(x,?y));points.Add(new?Point(x,?y?+?4));x?=?x?+?120;}drawingContext.DrawSnappedLinesBetweenPoints(myPen,?myPen.Thickness,?points.ToArray());var?xAxisPen?=?new?Pen{Thickness?=?1,Brush?=?(Brush)brushConverter.ConvertFromString("#E0E6F1")};xAxisPen.Freeze();var?xAxis?=?h?-?80;var?max?=?Convert.ToInt32(SeriesArray.Max(kvp?=>?kvp.Value));max?=?(max?/?50?+?(max?%?50?==?0???0?:?1))?*?50?/?50;var?min?=?Convert.ToInt32(SeriesArray.Min(kvp?=>?kvp.Value));points.Clear();for?(var?i?=?0;?i?<?max;?i++){//drawingContext.DrawLine(xAxisPen,?new?Point(startX,?xAxis),?new?Point(width,?xAxis));points.Add(new?Point(startX,?xAxis));points.Add(new?Point(width,?xAxis));stratNum?+=?50;formattedText?=?DrawingContextHelper.GetFormattedText(stratNum.ToString(),(Brush)brushConverter.ConvertFromString("#6E7079"),?FlowDirection.LeftToRight);drawingContext.DrawText(formattedText,new?Point(startX?-?formattedText.Width?-?10,?xAxis?-?formattedText.Height?/?2));xAxis?=?xAxis?-?80;}drawingContext.DrawSnappedLinesBetweenPoints(xAxisPen,?xAxisPen.Thickness,?points.ToArray());x?=?startX;var?rectWidth?=?85;var?rectHeight?=?0D;for?(var?i?=?0;?i?<?SeriesArray.Count();?i++){formattedText?=?DrawingContextHelper.GetFormattedText(SeriesArray.ToList()[i].Key,(Brush)brushConverter.ConvertFromString("#6E7079"),?FlowDirection.LeftToRight);drawingContext.DrawText(formattedText,?new?Point(x?+?120?/?2?-?formattedText.Width?/?2,?y?+?4));var?_value?=?SeriesArray.ToList()[i].Value;//rectHeight?=?_value?*?200;rectHeight?=?(_value?-?0)?/?(stratNum?-?0)?*?(80?*?max);//rectHeight?=?(stratNum?-?_value)?/?100?*?stratNum;drawingContext.DrawRectangle(rectBrush,?null,new?Rect(x?+?(120?-?85)?/?2,?h?-?rectHeight,?rectWidth,?rectHeight));x?=?x?+?120;}}}
}
2) **BasicBarChartExample.xaml ** 代碼如下;
<UserControl?x:Class="WPFDevelopers.Samples.ExampleViews.BasicBarChartExample"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:WPFDevelopers.Samples.ExampleViews"xmlns:wpfdev="https://github.com/WPFDevelopersOrg/WPFDevelopers"mc:Ignorable="d"?d:DesignHeight="450"?d:DesignWidth="800"><Grid?Background="Gainsboro"><BorderHeight="500"Background="White"Margin="30,0"><Grid?Margin="20,10"><Grid.RowDefinitions><RowDefinition?Height="40"?/><RowDefinition?/><RowDefinition?Height="auto"?/></Grid.RowDefinitions><WrapPanel?HorizontalAlignment="Right"><RectangleWidth="6"Height="26"Fill="Black"?/><TextBlockPadding="10,0"FontSize="24"FontWeight="Black"Text="{Binding?KeyBarChart,?RelativeSource={RelativeSource?AncestorType=local:BasicBarChartExample}}"?/></WrapPanel><wpfdev:BasicBarChartGrid.Row="1"SeriesArray="{Binding?SeriesModels,?RelativeSource={RelativeSource?AncestorType=local:BasicBarChartExample}}"/><ButtonGrid.Row="2"Width="200"VerticalAlignment="Bottom"Click="Button_Click"Content="刷新"Style="{StaticResource?PrimaryButton}"?/></Grid></Border></Grid>
</UserControl>
2) BasicBarChartExample .xaml.cs 代碼如下;
using?System;
using?System.Collections.Generic;
using?System.Linq;
using?System.Text;
using?System.Windows;
using?System.Windows.Controls;
using?System.Windows.Data;
using?System.Windows.Documents;
using?System.Windows.Input;
using?System.Windows.Media;
using?System.Windows.Media.Imaging;
using?System.Windows.Navigation;
using?System.Windows.Shapes;namespace?WPFDevelopers.Samples.ExampleViews
{///?<summary>///?BasicBarChartExample.xaml?的交互邏輯///?</summary>public?partial?class?BasicBarChartExample?:?UserControl{public?IEnumerable<KeyValuePair<string,?double>>?SeriesModels{get?{?return?(IEnumerable<KeyValuePair<string,?double>>)GetValue(SeriesModelsProperty);?}set?{?SetValue(SeriesModelsProperty,?value);?}}public?static?readonly?DependencyProperty?SeriesModelsProperty?=DependencyProperty.Register("SeriesModels",?typeof(IEnumerable<KeyValuePair<string,?double>>),?typeof(BasicBarChartExample),?new?PropertyMetadata(null));Dictionary<string,?IEnumerable<KeyValuePair<string,?double>>>?keyValues?=?new?Dictionary<string,?IEnumerable<KeyValuePair<string,?double>>>();public?string?KeyBarChart{get?{?return?(string)GetValue(KeyBarChartProperty);?}set?{?SetValue(KeyBarChartProperty,?value);?}}public?static?readonly?DependencyProperty?KeyBarChartProperty?=DependencyProperty.Register("KeyBarChart",?typeof(string),?typeof(BasicBarChartExample),?new?PropertyMetadata(null));private?int?_index?=?0;public?BasicBarChartExample(){InitializeComponent();var?Models1?=?new[]{new?KeyValuePair<string,?double>("Mon",?120),new?KeyValuePair<string,?double>("Tue",?130),new?KeyValuePair<string,?double>("Wed",?160),new?KeyValuePair<string,?double>("Thu",?140),new?KeyValuePair<string,?double>("Fri",?200)?,new?KeyValuePair<string,?double>("Sat",?80)?,new?KeyValuePair<string,?double>("Sun",?90)?,};keyValues.Add("到訪數",?Models1);var?Models2?=?new[]{new?KeyValuePair<string,?double>("蛐蛐",?120),new?KeyValuePair<string,?double>("常威",?170),new?KeyValuePair<string,?double>("來福",?30),new?KeyValuePair<string,?double>("包龍星",?200),new?KeyValuePair<string,?double>("包有為",?100)?,new?KeyValuePair<string,?double>("雷豹",?180)?,new?KeyValuePair<string,?double>("方唐鏡",?90)?,};keyValues.Add("能力值",?Models2);SeriesModels?=?keyValues.ToList()[0].Value;KeyBarChart?=?keyValues.ToList()[0].Key;}private?void?Button_Click(object?sender,?RoutedEventArgs?e){_index++;if?(_index?>=?keyValues.Count){_index?=?0;}SeriesModels?=?keyValues.ToList()[_index].Value;KeyBarChart?=?keyValues.ToList()[_index].Key;}}
}
