C# 如何在C中向柱状图顶部添加百分比#

C# 如何在C中向柱状图顶部添加百分比#,c#,charts,C#,Charts,所以,问题来了 我有一个图表,它使用以下循环显示了跨多个工作类型的两列(已完成和未完成): foreach (var workType in model.WorkTypes) { decimal completed = 0; decimal uncompleted = 0; decimal workSubmitted = 0; decimal completionRate= 0;

所以,问题来了

我有一个图表,它使用以下循环显示了跨多个工作类型的两列(已完成和未完成):

foreach (var workType in model.WorkTypes)
        {
            decimal completed = 0;
            decimal uncompleted = 0;
            decimal workSubmitted = 0;
            decimal completionRate= 0;
            foreach (var rec in model.JobList.Where(x => x.jobType== workType.Id))
            {
                uncompleted += model.JobList.SingleOrDefault(x => x.recID== rec.recID && x.jobType == workType.Id).Uncompleted;
                completed += model.JobList.SingleOrDefault(x => x.recID == rec.recID && x.jobType == workType.Id).Completed;

            }
            workSubmitted = uncompleted + completed;

            if (uncompleted != 0)
            {
                completionRate= (completed/ workSubmitted) * 100;
            }                
            myChart.Series["Uncompleted"].Points.AddXY(workType.TypeName, uncompleted );
            myChart.Series["Completed"].Points.AddXY(workType.TypeName, completed);
        }
我试图做的是让它在两列的上方显示一个标签,该标签将completionRate值显示为每个工作类型的百分比

任何帮助或建议都将不胜感激

这是图表的当前外观:

默认情况下,
标签
显示y值,但您可以为每个
数据点
设置任意的
标签
,例如,当您这样添加点时:

int p = myChart.Series["Uncompleted"].Points.AddXY(workType.TypeName, rejections);
myChart.Series["Uncompleted"].Points[p].Label = sometext;
当然,您可以根据需要计算标签的文本,例如:

string sometext = (workSubmitted / rejections * 100).ToString("0.00") + "%";
请注意,更改计算中的值后,必须更新
标签。不支持自动表达式

更新

正如我所写,在列共享的x值处放置一个
标签
居中,是很难的,甚至是不可能的;这是因为
标签属于单个数据点。这是柱形(和条形)图表的一个独特问题,因为在这里,系列的点显示在公共x值周围的簇中。(我们可以通过在中点添加标签来解决当且仅当序列数为奇数时的问题)

所以我们需要使用
注释
。这是一个函数,将
TextAnnotation
放置在两个数据点的x值和较大y值的高度处

void setCenterAnnotation(Chart chart, ChartArea ca, 
                         DataPoint dp1, DataPoint dp2, string lbl)
{
        TextAnnotation ta = new TextAnnotation();
        ta.Alignment = ContentAlignment.BottomCenter;
        ta.AnchorAlignment = ContentAlignment.TopCenter;
        DataPoint dp = dp1.YValues[0] > dp2.YValues[0] ? dp1 : dp2;
        ta.Height = 0.36f;
        ta.AxisX = ca.AxisX;
        ta.AxisY = ca.AxisY;
        ta.AnchorDataPoint = dp;
        ta.AnchorX = dp1.XValue;
        ta.Text =  lbl;
        chart.Annotations.Add(ta);
}
如果您有两个以上的
系列
,您最好确定锚点,即之前具有较大值的锚点,并传递它,而不是我在此传递的两个点

放置/锚定注释并不明显,因此这里有一些注意事项:

  • I锚定到一个
    数据点
    ,使其在y值的高度显示

  • 要使用(轴-)值进行锚定,必须为其指定一个或两个轴

  • I然后(顺序很重要!)设置
    AnchorX
    属性,使其不在点上居中,而是在公共x值上居中

  • 我还设置了一些
    高度
    ,否则文本不会在列顶部向上移动;不太清楚这里的理由是什么

结果如下:

我在添加点的同时添加了膏油:

int ix = s1.Points.AddXY(i, rnd.Next(i+7));
s2.Points.AddXY(i, rnd.Next(i+4)+3);
double vmax = Math.Max(s1.Points[ix].YValues[0], s2.Points[ix].YValues[0]);
string lbl = (vmax / 123f).ToString("0.0") + "%";
setCenterAnnotation(chart12, ca, s1.Points[ix], s2.Points[ix], lbl );

谢谢,这有点帮助,但我不想把它放在完成或未完成的顶部,而是放在整体组的顶部。什么是“整体组”?你能展示你拥有的和你想要的吗?我添加了一张带圆圈区域的图片。好吧,不幸的是,这比人们希望的要困难得多。我想不出比添加文本注释更好的解决方案;如果你真的想坚持非数值的x值,你应该首先了解x值丢失了,所有的点都有零(!!)。您仍然可以从其标签中找到一个点,可能如下所示
var hiz=chart1.Series[0].Points.Cast().Where(x=>x.AxisLabel==labelString.ToList()(可能不是唯一的)或通过
int ix=chart.Series[0].Points.IndexOf(dp1)从一个点查找索引
但是不能保证这将是一个有效的x值来停靠注释。我已经更新了答案。