我使用winform图表来显示数据, 我想显示标签,但图表非常拥挤。
有没有办法跳过,只显示每个 N 值的标签?
添加了图表系列:
var lastTrades = new Series("LastTrade") { ChartType = SeriesChartType.Line, XValueType = ChartValueType.DateTime, MarkerStyle = MarkerStyle.Circle };
lastTrades.IsValueShownAsLabel = true;
我在黑暗中用这些属性进行拍摄,但运气不佳:
lastTrades.SmartLabelStyle.Enabled = true;
lastTrades.SmartLabelStyle.IsOverlappedHidden = true;
欢迎提出建议。
最佳答案
一个Series
有一个DataPointCollection
在属性(property)Series.Points
.
DataPointCollection
是 ChartElementCollection<DataPoint>
,它实现 ICollection<DataPoint>
.
每个DataPoint
源自DataPointCustomProperties
它具有 bool 属性 DataPointCustomProperties.IsValueShownAsLabel
.
因此,您所要做的就是使用一种方法扩展这些集合类之一,为每个第 N 个元素将此属性设置为 true。
问题之一是,无法保证集合中 DataPoint 的顺序。因此,只需为每个第 N 个元素设置属性,它们可能会导致一堆彼此非常接近且具有标签的数据点。
示例:每 10 个元素一个标签
Index Position
0 [0, 0] label
1 [1, 0]
2 [2, 0]
...
8 [10, 0]
9 [0.001, 0] label
10 [0, 1]
11 [0, 2]
...
19 [0, 0.001] label
...
29 [0.001, 0.001] label
...
更好的解决方案是每个矩形只有一个点有标签。
因此,给定一系列数据点,您可以在同一矩形中创建多组数据点。之后,每个矩形仅选择一个数据点,假设最左下方的数据点获得一个标签。当然你想指定矩形的大小。
问题之一是每个 DataPoint 可能有多个 Y 值,并且所有 Y 值都会有一个标签。假设每个数据点只有一个 Y。我们将此 [X, Y] 值称为 Position of the DataPoint
。 X 和 Y 是 double 。
现在假设我们有宽度为 3 和高度为 2 的矩形。然后在水平方向上,矩形的间隔为 x= [0; 3),[3; 6)、[6, 9) 等以及垂直 [0; 2)、[2, 4) 等
如果您的 DataPoint 的位置为 [7, 3],则它位于第三个水平矩形、第二个垂直矩形或零索引:索引为 [2, 1] 的矩形中。
公式:计算X-index:(int)(position.X / Width)
对于 Y:(int)(position.Y / height)
double width = ...
double height = ...
Series mySeries = ...
var dataPointsWithLabel = mySeries.Points
// first calculate the (X, Y) Position of the DataPoint.
// Remember the original DataPoint
.Select(dataPoint => new
{
Position = new
{
X = dataPoint.XValue,
Y = dataPoint.YValues.FirstOrDefault(),
},
Value = dataPoint,
})
现在使用宽度和高度来计算矩形索引 记住原来的位置和原来的DataPoint,我们稍后需要它。
.Select(dataPoint => new
{
Position = dataPoint.Position
RectangleIndex = new
{
IndexX = (int)(dataPoint.Position.X / Width),
IndexY = (int)(dataPoint.Position.Y / Height),
}
Value = dataPoint,
})
使用相同的 RectangleIndex 进行分组:
.GroupBy(dataPoint => dataPoint.RectangleIndex,
// parameter resultSelector: take each rectangleIndex
// and all dataPoints that have an (X, Y) position in this rectangle
// to make one new:
(rectangleIndex, dataPointsInThisRectangle) => new
{
// todo: implement
});
现在,从该组中的所有数据点中,我们只想选择应该有标签的数据点。所有其他数据点将没有标签。
所以我们需要决定我们想要这个矩形中的哪个数据点?中间那个?最左边那个?你决定!
为了简单起见,我选择 X 最小的一个,如果有两个 X 相同,我选择 Y 最小的一个。所以我按 X 排序,然后按 Y 排序,并取第一个。
(rectangleIndex, dataPointsInThisRectangle) =>
// Order by X, then by Y
.OrderBy(dataPoint => DataPoint.Position.X)
.ThenBy(dataPoint => DataPoint.Position.Y)
// Select only the Value (which contains the original DataPoint)
.Select(dataPoint => dataPoint.Value)
// and keep only the first one:
.FirstOrDefault(),
因此,从您的系列中,我们选择了数据点,我们假设每个数据点只有一个 Y 值。我们计算了它的 (X, Y) 位置。我们计算了这个数据点将位于哪个矩形中。
我们在同一个矩形中创建了一组数据点。一组中的所有数据点均按 X 位置和 Y 位置排序。从排序结果中,我们获取了第一个数据点。
所以每个矩形我们只有一个数据点。此数据点是唯一具有标签的数据点。
foreach (var dataPoint in dataPointsWithLabel)
{
dataPoint.IsValueShownAsLabel = true;
}
关于c# - 如何在Y轴上每N个值显示标签?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63773610/