Wpf中使用LiveCharts绘制堆叠柱状图求助:新手技术问询
实现WPF LiveCharts堆叠柱状图展示每日活动时间段
嘿,刚上手WPF和LiveCharts的话,这种按天展示时间段状态的堆叠柱状图其实很好实现,我给你梳理一套完整的方案,包含数据模型、ViewModel和XAML代码,直接就能用~
1. 先准备数据模型和ViewModel
首先得把数据结构理清楚,让LiveCharts能轻松绑定我们的每日状态数据。
数据模型类
先创建一个类来存储单天的各状态时长统计:
public class DailyStatusData { public DateTime Date { get; set; } public double AbsentHours { get; set; } // 缺席总时长 public double Activity1Hours { get; set; } // 活动1总时长 public double Activity2Hours { get; set; } // 活动2总时长 // 后续新增状态直接加对应属性即可 }
ViewModel(核心逻辑)
ViewModel负责把原始数据转换成LiveCharts需要的系列格式,同时处理轴标签:
using LiveCharts; using LiveCharts.Wpf; using System.Collections.Generic; using System.Linq; using System.Windows.Media; public class ActivityChartViewModel { // X轴显示的日期标签(比如"Day1", "Day2") public List<string> DateLabels { get; set; } // 堆叠柱状图的系列集合 public SeriesCollection StatusSeries { get; set; } // Y轴标签格式化器(显示整数小时) public Func<double, string> YAxisLabelFormatter => value => $"{value:F0}h"; public ActivityChartViewModel() { // 模拟你给出的需求数据 var dailyData = new List<DailyStatusData> { new DailyStatusData { Date = DateTime.Now.AddDays(-1), AbsentHours = 8 + 11, // 0-8点 + 12-23点的缺席时长 Activity1Hours = 3, // 9-12点的活动1时长 // 活动2时长为0,当天无该状态 }, new DailyStatusData { Date = DateTime.Now, AbsentHours = 10, // 0-10点的缺席时长 Activity2Hours = 2, // 10-12点的活动2时长 // 活动1时长为0,当天无该状态 } }; // 生成X轴标签,也可以改成显示具体日期如"2024-05-20" DateLabels = dailyData.Select((d, idx) => $"Day{idx+1}").ToList(); // 初始化堆叠系列,每个状态对应一个系列 StatusSeries = new SeriesCollection { // 缺席系列(红色) new StackedColumnSeries { Title = "缺席", Values = new ChartValues<double>(dailyData.Select(d => d.AbsentHours)), Fill = Brushes.Red }, // 活动1系列(绿色) new StackedColumnSeries { Title = "活动1", Values = new ChartValues<double>(dailyData.Select(d => d.Activity1Hours)), Fill = Brushes.Green }, // 活动2系列(黄色) new StackedColumnSeries { Title = "活动2", Values = new ChartValues<double>(dailyData.Select(d => d.Activity2Hours)), Fill = Brushes.Yellow } }; } }
2. XAML布局(视图部分)
在WPF窗口中添加LiveCharts控件,配置轴参数并绑定数据:
<Window x:Class="WpfLiveChartsDemo.ActivityChartWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf" xmlns:local="clr-namespace:WpfLiveChartsDemo" Title="每日活动分布" Height="450" Width="800"> <Window.DataContext> <local:ActivityChartViewModel/> </Window.DataContext> <Grid> <lvc:CartesianChart Series="{Binding StatusSeries}" LegendLocation="Right"> <!-- X轴:绑定日期标签 --> <lvc:CartesianChart.AxisX> <lvc:Axis Title="日期" Labels="{Binding DateLabels}"/> </lvc:CartesianChart.AxisX> <!-- Y轴:固定0-24小时,绑定格式化器 --> <lvc:CartesianChart.AxisY> <lvc:Axis Title="小时" MinValue="0" MaxValue="24" LabelsFormatter="{Binding YAxisLabelFormatter}"/> </lvc:CartesianChart.AxisY> </lvc:CartesianChart> </Grid> </Window>
3. 关键细节说明
- 空白区域(未知状态):如果当天所有状态的时长总和小于24,柱子顶部到24小时刻度的空白部分就代表未知状态,完全符合你的需求~
- 状态扩展:以后要加新活动状态,只需要在
DailyStatusData里新增对应时长属性,再在StatusSeries里添加一个新的StackedColumnSeries就行。 - 日期格式自定义:如果不想显示"Day1"这种标签,直接修改
DateLabels的生成逻辑,比如d.Date.ToString("yyyy-MM-dd")就能显示具体年月日。
4. 注意事项
- 记得通过NuGet安装
LiveCharts.Wpf包,建议选最新稳定版; - 如果需要更精细的时间段拆分(比如不合并同一天的同状态时长),可以把每个时间段作为独立数据点处理,但当前合并同状态的方式更简洁直观,适合展示每日分布。
内容的提问来源于stack exchange,提问作者Laminos
相关产品推荐
相关产品推荐

