【问题标题】:C# WinForms application: dual-color column in stacked chartC# WinForms 应用程序:堆叠图表中的双色列
【发布时间】:2016-12-17 16:05:29
【问题描述】:

我是一名 .NET 开发人员。我正在开发一个 Windows 窗体应用程序,这张图片显示我想使用图表控件:

基本上,我想更改高于某个阈值(上例中为 400)的每列的上部。我已经搜索了一下,但还没有快乐。有什么想法吗?

编辑:我有一个优雅的解决方法,但是控件本身没有可用的东西仍然令人沮丧。我创建了两个系列,红色和蓝色。当我添加一个点时,我会检查高度是否大于阈值。如果是,我将这个点添加到红色系列中,我还将一个阈值高度点添加到蓝色系列中。如果没有,我将它按原样添加到蓝色系列中。代码比我能解释的好:

    private void AddPointToChart(Chart chart, int x, int y)
    {
        if (this.threshold < y)
        {
            chart.Series[1].Points.AddXY(x, y);
            y = this.threshold;
        }

        chart.Series[0].Points.AddXY(x, y);
    }

【问题讨论】:

  • 这个项目是否使用了图表控件?
  • 是的。为了清楚起见,我已经编辑了我的问题
  • 1) 你确定你真的在使用stackedColumn图表吗? - 2) 一列只能有一种颜色;你必须自己画它..
  • @TaW 1) 100℅ 2) 您也可以使用帖子中描述的 2 系列的技巧。

标签: c# winforms charts


【解决方案1】:

根据最初的问题,StackedColumn 是要走的路!

对于您的编辑,on 选项(不是一个简单的选项)是覆盖 Chart 的虚拟方法以添加您自己的行为。经过一些实验,我想出了一个例子:

public class ThresholdColumnChart : Chart
{
    private double _threshold = 50d;

    public double Threshold
    {
        get { return _threshold; }
        set { _threshold = value; Invalidate(); }
    }

    public ThresholdColumnChart() : base() { }

    protected override void OnCustomize()
    {
        base.OnCustomize();

        if (Series.Count != 1)
            return;

        Series.Add(new Series());

        foreach (var dataPoint in Series[0].Points)
        {
            var newDataPoint = new DataPoint();

            newDataPoint.XValue = dataPoint.XValue;
            newDataPoint.YValues[0] = (dataPoint.YValues[0] > _threshold ? 
                 dataPoint.YValues[0] - _threshold : 0);

            Series[1].Points.Add(newDataPoint);

            if (dataPoint.YValues[0] > _threshold)
                dataPoint.YValues[0] = _threshold;
        }

        Series[0].ChartType = SeriesChartType.StackedColumn;
        Series[1].ChartType = SeriesChartType.StackedColumn;
        Series[1].Color = Color.Red;
    }

    protected override void OnPostPaint(ChartPaintEventArgs e)
    {
        base.OnPostPaint(e);

        if (!(e.ChartElement is ThresholdBarChart))
            return;

        if (Series.Count != 2)
            return;

        for (int i = 0; i < Series[0].Points.Count; i++)
            Series[0].Points[i].YValues[0] += Series[1].Points[i].YValues[0];

        Series.Remove(Series[1]);
    }
}

简而言之,在绘制图表之前(OnPrePaint(...) 之前)调用 OnCustomize(...) 方法,此时它会创建第二个用于绘制的系列。新系列是在考虑阈值的情况下构建的,并且第一个系列会减少到不超过阈值,就像您编辑中的示例一样。

图表绘制完成后,OnPostPaint(...) 将被调用,第一个系列将恢复为原始值,“额外”系列将被删除。

在绘制图表时,OnPrePaint(...)OnPostPaint 实际上都被多次调用,因此我必须将 if (!(e.ChartElement is ThresholdBarChart)) return; 放入;以确保我们仅在图表完成绘制后才删除该系列。

添加代码并编译后,您将在设计工具箱中添加一个名为“ThresholdColumnChart”的新用户控件。您可以从属性“阈值”(也在设计中)设置阈值。我不会用我的生命相信这段代码,但它应该作为一个起点。

【讨论】:

    猜你喜欢
    • 2017-11-11
    • 1970-01-01
    • 1970-01-01
    • 2011-07-02
    • 1970-01-01
    • 2020-06-03
    • 2014-08-15
    • 2019-10-26
    • 1970-01-01
    相关资源
    最近更新 更多