如何获取自动排列后的chart area最终宽度以正确设置柱状图列宽
解决方案
你需要等Chart控件完成所有ChartArea的自动布局计算后,读取对应ChartArea的实际绘图区域宽度再计算列宽,原代码直接用Chart总宽度计算没有考虑多ChartArea的布局分配、ChartArea内边距、坐标轴标签占用的空间,才会出现多列布局下宽度不符合预期的问题。
具体实现方法
有两种常用的实现方式,按需选择即可:
- 方式1:使用PrePaint事件(推荐,适配所有动态布局场景)
Chart的PrePaint事件会在所有布局计算完成后、元素渲染前触发,此时读取的ChartArea尺寸是最终的实际像素尺寸,示例代码如下:
首先在Chart初始化阶段绑定事件:
事件处理逻辑:AddHandler chart1.PrePaint, AddressOf Chart1_PrePaintPrivate Sub Chart1_PrePaint(sender As Object, e As ChartPaintEventArgs) ' 仅处理ChartArea级别的绘制前事件,避免重复执行 If Not TypeOf e.ChartElement Is ChartArea Then Return Dim targetArea As ChartArea = CType(e.ChartElement, ChartArea) ' 跳过已经完成宽度设置的ChartArea,避免重复赋值 If chart1.Series.Any(Function(s) s.ChartArea = targetArea.Name AndAlso Not String.IsNullOrEmpty(s("PixelPointWidth"))) Then Return End If ' 计算实际绘图区域的像素宽度:InnerPlotPosition为相对Chart总宽度的百分比 Dim plotWidthPx As Integer = CInt(chart1.Width * targetArea.InnerPlotPosition.Width / 100) ' myNumIntervals替换为当前ChartArea对应系列的柱子总数量 Dim columnWidth As Integer = CInt(plotWidthPx / myNumIntervals) ' 为归属当前ChartArea的所有系列设置列宽 For Each series In chart1.Series.Where(Function(s) s.ChartArea = targetArea.Name) series("PixelPointWidth") = columnWidth.ToString() Next End Sub - 方式2:手动触发布局计算(适合静态一次性渲染场景)
如果你所有的ChartArea、系列、数据都是一次性添加完成,不需要后续动态更新,可以在所有内容配置完成后手动触发布局计算,直接读取尺寸:' 所有ChartArea、数据添加完成后执行 chart1.PerformLayout() For Each area As ChartArea In chart1.ChartAreas Dim plotWidthPx As Integer = CInt(chart1.Width * area.InnerPlotPosition.Width / 100) Dim columnWidth As Integer = CInt(plotWidthPx / myNumIntervals) For Each series In chart1.Series.Where(Function(s) s.ChartArea = area.Name) series("PixelPointWidth") = columnWidth.ToString() Next Next
注意事项
不要使用ChartArea.Position来计算宽度,这个属性返回的是包含坐标轴、标签、ChartArea标题的总区域宽度,实际绘图可用区域比这个值小,用InnerPlotPosition计算得到的列宽会更贴合实际显示需求。
内容的提问来源于stack exchange,提问作者user16594857
相关产品推荐
相关产品推荐

