WPF实现统计图

43785eb5c765fc055ddd463c46cfec27.png

WPF开发者QQ群: 340500857  | 微信群 -> 进入公众号主页 加入组织

dd06d688031910754a44dfadc4ae7fc8.png 

8d5842d914d7c1a72f915c191138542d.png

有小伙伴提出需要实现统计图。                           

     由于在WPF中没有现成的统计图控件,所以我们自己实现一个。

PS:有更好的方式欢迎推荐。

01

代码如下

一、创建 BasicBarChart.cs 菜单继承 Control代码如下。

ed04799205e2cc914d59c66bbd266265.png

BasicBarChart.cs实现思路如下

1、SeriesArray :存放展示集合 。

2、重写OnRender 。

3、先绘制X轴线。

4、调用GetFormattedText()绘制底部类别。

5、调用GetFormattedText()绘制左侧标尺。

6、DrawingContext绘制Line的时候会发虚,以下方法可以避免

 var d = Pen.Thickness / 2;

 var guidelines = new GuidelineSet(new[] { d }, new[] { d });

drawingContext.PushGuidelineSet(guidelines);

或者调用

SnapDrawingExtensions.DrawSnappedLinesBetweenPoints

避免画线发虚。

2b7f035049897ad2941d121e96af4b70.png

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;namespace WPFDevelopers.Controls
{public class BasicBarChart : Control{public IEnumerable<KeyValuePair<string, double>> SeriesArray{get { return (IEnumerable<KeyValuePair<string, double>>)GetValue(SeriesArrayProperty); }set { SetValue(SeriesArrayProperty, value); }}public static readonly DependencyProperty SeriesArrayProperty =DependencyProperty.Register("SeriesArray", typeof(IEnumerable<KeyValuePair<string, double>>), typeof(BasicBarChart), new UIPropertyMetadata(SeriesArrayChanged));private static void SeriesArrayChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){BasicBarChart radarChart = d as BasicBarChart;if (e.NewValue != null)radarChart.InvalidateVisual();}static BasicBarChart(){DefaultStyleKeyProperty.OverrideMetadata(typeof(BasicBarChart), new FrameworkPropertyMetadata(typeof(BasicBarChart)));}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 = this.ActualHeight / 2 + 160;var w = this.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;SnapDrawingExtensions.DrawSnappedLinesBetweenPoints(drawingContext,myPen,myPen.Thickness, new Point(startX, h), new Point(width, h));var formattedText = GetFormattedText(stratNum.ToString());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 (int 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;}SnapDrawingExtensions.DrawSnappedLinesBetweenPoints(drawingContext, myPen, myPen.Thickness, points.ToArray());var xAxisPen = new Pen{Thickness = 1,Brush = (Brush)brushConverter.ConvertFromString("#E0E6F1")};xAxisPen.Freeze();var xAxis = h - 80;int max = Convert.ToInt32(SeriesArray.Max(kvp => kvp.Value));max = (max / 50 + (max % 50 == 0 ? 0 : 1)) * 50 / 50;int min = Convert.ToInt32(SeriesArray.Min(kvp => kvp.Value));points.Clear();for (int 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 = GetFormattedText(stratNum.ToString());drawingContext.DrawText(formattedText, new Point(startX - formattedText.Width - 10, xAxis - formattedText.Height / 2));xAxis = xAxis - 80;}SnapDrawingExtensions.DrawSnappedLinesBetweenPoints(drawingContext, xAxisPen, xAxisPen.Thickness, points.ToArray());x = startX;var rectWidth = 85;var rectHeight = 0D;for (int i = 0; i < SeriesArray.Count(); i++){formattedText = GetFormattedText(SeriesArray.ToList()[i].Key);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;}}FormattedText GetFormattedText(string text){var brushConverter = new BrushConverter();return new FormattedText(text,CultureInfo.CurrentCulture,FlowDirection.LeftToRight,new Typeface(new FontFamily("Microsoft YaHei"), FontStyles.Normal, FontWeights.UltraLight, FontStretches.Normal),12, (Brush)brushConverter.ConvertFromString("#6E7079")){MaxLineCount = 1,TextAlignment = TextAlignment.Justify,Trimming = TextTrimming.CharacterEllipsis};}}public static class SnapDrawingExtensions{public static void DrawSnappedLinesBetweenPoints(this DrawingContext dc,Pen pen, double lineThickness, params Point[] points){var guidelineSet = new GuidelineSet();foreach (var point in points){guidelineSet.GuidelinesX.Add(point.X);guidelineSet.GuidelinesY.Add(point.Y);}var half = lineThickness / 2;points = points.Select(p => new Point(p.X + half, p.Y + half)).ToArray();dc.PushGuidelineSet(guidelineSet);for (var i = 0; i < points.Length - 1; i = i + 2){dc.DrawLine(pen, points[i], points[i + 1]);}dc.Pop();}}
}

二、创建BasicBarChartExample.xaml代码如下

2ebcc34d5622d75d27105e8c6c99d435.png

<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/yanjinhuagood/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>

三、创建BasicBarChartExample.xaml.cs代码如下

a2fbdf33e30d673fcccdf88373ce118d.png

/// <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;}

02


效果预览

上一篇雷达图更新了

5e0a46131401d21499f4aa8c4640846a.gif

源码地址如下

github:https://github.com/yanjinhuagood/WPFDevelopers.git

gitee:https://gitee.com/yanjinhua/WPFDevelopers.git

WPF开发者QQ群: 340500857 

blogs: https://www.cnblogs.com/yanjinhua

Github:https://github.com/yanjinhuagood

出处:https://www.cnblogs.com/yanjinhua

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

转载请著名作者 出处 https://github.com/yanjinhuagood

8fb6774e53ba68d94b89ea34120ba8e7.png

扫一扫关注我们,

d0fdcdf3cc921b43c98d0465c15b8682.gif

更多知识早知道!

146be20e47e8346c787329482015a955.gif

点击阅读原文可跳转至源代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/296226.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

手绘图解:从零维到十维空间

全世界只有3.14 % 的人关注了爆炸吧知识事情是这样的&#xff0c;这周我给学生讲3dmax的课。为了让学生了解三视图我就顺便科普了一下什么是零维、一维、二维、三维空间。讲完不过瘾&#xff0c;感觉一支粉笔一块黑板讲维度是一件很爽的事情&#xff0c;那么.........接下来请同…

ISA server的常见身份验证方式

ISA 2006的几种常用验证方式&#xff1a;1. 基本验证&#xff1a;此验证方式不会被加密&#xff0c;只是以明文的方式来传递信息&#xff0c;不安全。如果在“网络”的“内部”属性中将“域”选项卡里边的“选择域”来配置默认域&#xff0c;那么就会把用户送来的帐户与密码信息…

字节前端终于开源!吹爆!

Semi Design 发布&#xff0c;前端同学的福音大家好&#xff0c;我是鱼皮。最近&#xff0c;字节跳动的抖音前端技术团队开源了一款企业级应用设计系统 Semi Design 。这也是他们团队在 GitHub 上首次公开的项目&#xff0c;短短几天&#xff0c;就收获了 3.6 k 个 star。GitH…

CSS2-3常见的demo列子总结

CSS2-3常见的demo列子总结 阅读目录 1. css超过一行或者多行后显示省略号。2. css图片未知高度垂直居中完美解决方案。3. 学习使用 :before和 :after伪元素回到顶部1. css超过一行或者多行后显示省略号。 Css实现超过一行后显示省略号&#xff1b;代码如下&#xff1a;<p st…

18张难以置信的照片,封面这张你就没见过

全世界只有3.14 % 的人关注了爆炸吧知识感谢网络&#xff0c;只要点几下鼠标&#xff0c;就能看到我们以前从未见过的东西——有些甚至是难以置信的&#xff01;鲸鱼的心脏水中的鲨鱼卵幼年的箭鱼萌萌哒世界上最高的棕榈树&#xff0c;简直以为是PS的没见过的话&#xff0c;很容…

.NET 生态系统的蜕变之 .NET 6

.NET 6 是自.NET 4 框架以来生态系统看到的最大版本更新&#xff0c;虽然.NET Core 是2014年开始非常大的一项重大战略举措&#xff0c;但是.NET 6是真正的具有强大动力的非常重要的版本。2021年11月9日即将正式发布的.NET 6, 也许你认为.NET 5才刚刚发布&#xff0c;我才刚开始…

我看你还能坚持多久?!

1 我看你还能坚持多久&#xff01;▼2 依旧是熟悉的配方▼3 到哪儿都不愁工作......▼4 请问&#xff0c;当事喵作何感想&#xff1f;▼5 池塘危险&#xff0c;请勿靠近&#xff01;&#xff08;图源网络&#xff0c;侵删&#xff09;▼6 望周知&#xff01;▼7 实在是无…

Hello Blazor:(13)查找HTML元素对应.razor文件

前言Blazor是基于组件的开发&#xff0c;每个组件都是以一个.razor文件形式存在。当应用程序变得越来越大并且.razor文件的数量和层次结构越来越多时&#xff0c;想很快弄清页面上的HTML元素是由哪个组件生成的&#xff0c;就变得不那么容易了&#xff01;FindRazorSourceFile介…

C++STL之string (转)

在学习cSTL中的string&#xff0c;在这里做个笔记&#xff0c;以供自己以后翻阅和初学者参考。 1&#xff1a;string对象的定义和初始化以及读写 string s1; 默认构造函数&#xff0c;s1为空串 string s2(s1); 将s2初始化为s1的一个副本 string s3("valuee");…

当年的毒王熊猫烧香,现在怎么样了?

全世界只有3.14 % 的人关注了爆炸吧知识放假&#xff0c;小编来到了远在73公里之外的天后宫&#xff0c;终于是了了本命年的一桩心事。回想上一个本命年&#xff0c;当时小编还是沉迷扫雷和蜘蛛纸牌的孩子...但当时却发生了一件令我很不爽的事——“熊猫烧香”席卷全国&#xf…

$query php,phpQuery让php处理html代码像jQuery一样方便

简介如何在php中方便地解析html代码&#xff0c;估计是每个phper都会遇到的问题。用phpQuery就可以让php处理html代码像jQuery一样方便。DEMO我下的是onefile版&#xff1a;phpQuery-0.9.5.386-onefile.zip然后在项目中引用。html文件test.html&#xff1a;Spiderman City Driv…

那个成人总会遇到的小问题……

结语超模君就问问&#xff1a;我还有机会10万&#xff0b;吗&#xff1f;&#xff08;溜了溜了&#xff09;莱布尼茨德国数学家莱布尼茨&#xff0c;被后人誉为“百科全书式的天才”&#xff0c;他的研究涉及逻辑学、力学等40多个领域。他创建了数学理论&#xff1a;微积分学。…

java继承接口和泛型,JavaSE习题 继承接口和泛型

问答题&#xff1a;1.子类在什么情况下可以继承父类友好成员&#xff1f;答&#xff1a;在同一个包内2.子类通过怎样的方法可以隐藏继承的成员变量&#xff1f;答&#xff1a;声明一个与父类相同变量名的成员变量3.子类重写继承的方法原则是什么&#xff1f;答&#xff1a;保证…

Github CodeSpaces 使用及定制化

Github CodeSpaces 使用及定制化IntroGithub 最近推出了很多令人兴奋的新功能&#xff0c;最近使用了 Github CodeSpaces&#xff0c;觉得还是挺不错的&#xff0c;CodeSpaces 相当于自己有了一个云主机&#xff0c;真正实现了云端开发&#xff0c;CodeSpaces 和 Github 做了很…

nat+端口转发,使得宿主机secureCRT可以访问vbox里linux虚拟机

为什么80%的码农都做不了架构师&#xff1f;>>> 环境&#xff1a;vbox或者叫vitrualbox连接虚拟机&#xff0c;由于公司内网不能分配IP&#xff08;不知道是不是这个原因&#xff09;&#xff0c;虚拟机用桥接得不到IP&#xff0c;没法实现虚拟机和宿主互相访问&am…

男人可以有多敷衍?

1 现在更流行「红茶女生」&#xff1f;&#xff08;via.白头叔&#xff09;▼2 谢谢&#xff0c;有被冒犯到&#xff08;素材来源网络&#xff0c;侵删&#xff09;▼3 天使与恶魔▼4 男朋友可以多敷衍&#xff1f;▼5 你的高原红&#xff0c;像极了妈妈的巴掌印&#xff…

linux 内核代码构架图

转载于:https://www.cnblogs.com/kuainiao/archive/2012/12/17/2822384.html

Win11开始大范围推送!

微软宣布 Windows11 现已开始向更多符合最低硬件要求的电脑推送。预计到 2022 年年中&#xff0c;所有符合条件的电脑都可以免费升级到 Windows 11。微软将根据硬件条件、可靠性、使用时间&#xff0c;及其它会影响升级后使用体验的因素&#xff0c;为 Windows 10 电脑分阶段推…

有什么看起来很难,但是其实很简单的题目

全世界只有3.14 % 的人关注了爆炸吧知识做题其实很简单今天超模君一进办公室就感觉充满“杀气”&#xff0c;果不其然&#xff0c;一抬头就看见小天拿着一张纸对着我坏笑。莫非这家伙又要我折纸&#xff1f;拿过纸张一看&#xff0c;虽然密密麻麻的一大堆公式&#xff0c;但我相…

双11,2分钟狂挣20亿的神秘大厂,急招.NET!

双11小米开门红&#xff0c;2分钟不到突破20亿&#xff0c;于是机智的我又去逛了下小米的招聘官网&#xff1a;招5年左右.NET&#xff0c;35k左右&#xff0c;14薪&#xff0c;要求WPF和自动化&#xff0c;真香&#xff01;回首牛年2个跳槽季&#xff0c;招WPF的大厂太多了&…