WPF 实现柱形统计图

 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;}}
}
5e32ef9803210a13b60f15bb722fbaa6.png

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

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

相关文章

Win11卸载WSL,卸载Windows子系统

虽然 Linux 发行版可以通过 Microsoft Store 安装&#xff0c;但不能通过 Microsoft Store 卸载。 可以通过下列命令卸载。 1、查看当前环境安装的wsl wsl --list2、注销&#xff08;卸载&#xff09;当前安装的Linux的Windows子系统 wsl --unregister Ubuntu3、卸载成功&#…

100亿人口会挨饿吗?人工智能迎击全球粮食问题

给作物看病的AI、走路“长眼”的拖拉机、上帝视角的卫星数据分析——未来吃饭就靠它们了。 图片来源&#xff1a;Blue River Technology 人类又面临了一项危机——随着人口不断膨胀&#xff0c;到2050年人类总人口也许要达到100亿&#xff0c;然而&#xff0c;地球却没有等比例…

Python学习总结15:时间模块datetime time calendar (二)

二 、datetime模块 1. datetime中常量 1&#xff09;datetime.MINYEAR&#xff0c;表示datetime所能表示的最小年份&#xff0c;MINYEAR 1。 2&#xff09;datetime.MAXYEAR&#xff0c;表示datetime所能表示的最大年份&#xff0c;MAXYEAR 9999。 2. datetime中的常见类 da…

switch注意事项

Day03_SHJavaTraining_4-5-2017 switch注意事项&#xff1a;①switch语句接受的数据类型  switch语句中的表达式的数据类型,是有要求的    JDK1.0 - 1.4 数据类型接受 byte short int char    JDK1.5 数据类型接受 byte short int char enum(枚举)  …

WSL1 和 WSL2对比

从 WSL1 更新到 WSL2的主要原因包括&#xff1a; 提高文件系统性能&#xff0c;支持完全的系统调用兼容性。 WSL 2 使用最新、最强大的虚拟化技术在轻量级实用工具虚拟机 (VM) 中运行 Linux 内核。 但是&#xff0c;WSL 2 不是传统的 VM 体验。 ​ 本指南将比较 WSL 1 和 WSL …

SkiaSharp 之 WPF 自绘 粒子花园(案例版)

此案例包含了简单的碰撞检测&#xff0c;圆形碰撞检测方法&#xff0c;也可以说是五环弹球的升级版&#xff0c;具体可以根据例子参考。粒子花园这名字是案例的名字&#xff0c;效果更加具有科技感&#xff0c;很是不错&#xff0c;搞搞做成背景特效也是不错的选择。Wpf 和 Ski…

xshell连接ubuntu

1.更新资料列表 sudo apt-get update2.安装openssh-server sudo apt-get install openssh-server3.查看ssh服务是否启动 sudo ps -e | grep ssh4.如果没有启动&#xff0c;启动ssh服务 sudo service ssh start5.查看IP地址 sudo ifconfig如果出现xshell无法输入密码的情况…

教你从零开始搭建一款前端脚手架工具

本文系原创&#xff0c;转载请附带作者信息&#xff1a;Jrain Lau项目地址&#xff1a;https://github.com/jrainlau/s...前言 在实际的开发过程中&#xff0c;从零开始建立项目的结构是一件让人头疼的事情&#xff0c;所以各种各样的脚手架工具应运而生。笔者使用较多的yoeman…

微信小程序 --- 页面跳转

第一种&#xff1a;wx.navigateTo({}); 跳转&#xff1a; 注意&#xff1a;这种跳转回触发当前页面的 onHide 方法&#xff0c;将当前页面隐藏&#xff0c;然后显示跳转页面。所以可以返回&#xff0c;返回的时候触发 onShow方法进行显示&#xff1a; &#xff08;项目的底部导…

Java基础 深拷贝浅拷贝

Java基础 深拷贝浅拷贝 非基本数据类型 需要new新空间class Student implements Cloneable{private int id;private String name;private Vector course;public Student(){try{Thread.sleep(1000);System.out.println("Student Constructor called.");}catch (Interr…

不安装运行时运行 .NET 程序

好久没写文章了&#xff0c;有些同学问我公众号是不是废了&#xff1f;其实并没有。其实想写的东西很多很多&#xff0c;主要是最近公司比较忙&#xff0c;以及一些其他个人原因没有时间来更新文章。这几天抽空写了一点点东西&#xff0c;证明公众号还活着。长久以来的认知&…

一文弄懂分布式和微服务

简单的说&#xff0c;微服务是架构设计方式&#xff0c;分布式是系统部署方式&#xff0c;两者概念不同。 微服务 简单来说微服务就是很小的服务&#xff0c;小到一个服务只对应一个单一的功能&#xff0c;只做一件事。这个服务可以单独部署运行&#xff0c;服务之间可以通过R…

常见的js算法面试题收集,es6实现

1、js 统计一个字符串出现频率最高的字母/数字 let str asdfghjklaqwertyuiopiaia; const strChar str > {let string [...str],maxValue ,obj {},max 0;string.forEach(value > {obj[value] obj[value] undefined ? 1 : obj[value] 1if (obj[value] > max)…

PHP面向对象(OOP)----分页类

PHP面向对象(OOP)----分页类 同验证码类&#xff0c;分页也是在个人博客&#xff0c;论坛等网站中不可缺少的方式&#xff0c;通过分页可以在一个界面展示固定条数的数据&#xff0c;而不至于将所有数据全部罗列到一起&#xff0c;实现分页的原理其实就是对数据库查询输出加了一…

JS 事件练习

QQ拖拽及状态栏选择 HTML 1 <!DOCTYPE html>2 <html xmlns"http://www.w3.org/1999/xhtml">3 <head>4 <title>QQ练习</title>5 <link href"css/main.css" rel"stylesheet" />6 <script src&…

Dubbo和Spring Cloud微服务架构对比

微服务架构是互联网很热门的话题&#xff0c;是互联网技术发展的必然结果。它提倡将单一应用程序划分成一组小的服务&#xff0c;服务之间互相协调、互相配合&#xff0c;为用户提供最终价值。目录 微服务主要的优势 降低复杂度 可独立部署 容错 扩展 核心部件 总体架构 Dubbo …

《ABP Framework 极速开发》 - 教程首发

‍写在发布之前强烈建议每一位小伙伴都应该好好看看 ABP Framework 官方文档&#xff0c;可能有很多的小伙伴跟我刚开始的感觉一样“一看文档深似海”&#xff0c;看完文档之后&#xff0c;想要上手却找不着头绪。本套教程写作的目的之一是为初学者提供一条相对简洁的快速上手路…

智能家居系统结构标准化

版权申明&#xff1a;本文为博主窗户(Colin Cai)原创&#xff0c;欢迎转帖。如要转贴&#xff0c;必须注明原文网址http://www.cnblogs.com/Colin-Cai/p/8490423.html作者&#xff1a;窗户QQ&#xff1a;6679072E-mail&#xff1a;6679072qq.com0 引 言 智能家居是指利用先进的…

洛谷 P3391 文艺平衡树

题目描述 您需要写一种数据结构&#xff08;可参考题目标题&#xff09;&#xff0c;来维护一个有序数列&#xff0c;其中需要提供以下操作&#xff1a;翻转一个区间&#xff0c;例如原有序序列是5 4 3 2 1&#xff0c;翻转区间是[2,4]的话&#xff0c;结果是5 2 3 4 1 --by洛谷…

JSONObject中optString和getString等的区别

2019独角兽企业重金招聘Python工程师标准>>> 同事在看到我写的解析数据代码后&#xff0c;告诉我optString比getString好用&#xff0c;optString不会抛异常&#xff0c;而getString会抛异常&#xff0c;自己是将信将疑&#xff0c;就说&#xff0c;回去后我查查资料…