c# - 如何在Y轴上每N个值显示标签?

标签 c# winforms charts

我使用winform图表来显示数据, 我想显示标签,但图表非常拥挤。

enter image description here

有没有办法跳过,只显示每个 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 .

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

相关文章:

c# - 如何使用 C# .NET 4 实现 DDD

c# - 使用 C# 导出到 OneNote

c# - 如果今天是星期一,我如何获得星期五日期

c# - 在我的 winforms 应用程序中检测以太网端口插入/移除?

javascript - jquery 或 javascript 中的图表

c# - 正则表达式 : take string literally with special re-characters

c# - 查找图表中点的值

c# - 具有最近邻过滤图像裁剪边缘的winforms图形

android - MPAndroidChart 对数 Y 轴

java - 我如何绘制 Java 中非常小的值?