Столбчатая диаграмма с накоплением в диаграмме Microsoft имеет пробелы

Я использую библиотеку Chart в .Net 4.0 для создания гистограммы с накоплением из нескольких рядов. Моя цель — гистограмма, показывающая совокупное количество действий (завершений отчетов) в день по нескольким сериям (учителям). Часто отсутствуют данные (отсутствие активности в этот день у конкретного учителя).

Я получаю пробелы в столбцах, когда в серии отсутствуют данные:

Гистограмма с пробелами в столбцах

Мой код:

    public ActionResult CompletionHistogram(int sid, int width, int height)
    {
        Site site = SiteRepository.Get(sid);
        if (site == null)
            return new HttpNotFoundResult();

        Chart chart = new Chart();
        chart.Height = height;
        chart.Width = width;
        ChartArea area = chart.ChartAreas.Add("Default");

        // Treat each teacher as a series
        foreach (Teacher t in site.Teachers)
        {
            Series series = chart.Series.Add(t.FullName);
            series.ChartType = SeriesChartType.StackedColumn;
            series.Name = t.FullName;

            // Group completions by day (filter out incomplete reports and null timestamps)
            var groups = t.StudentReports
                .Where<StudentReport>(rep => rep.IsComplete && rep.FirstSaveTimestamp.HasValue)
                .GroupBy<StudentReport, DateTime>(rep => rep.FirstSaveTimestamp.Value.Date);

            bool hasPoints = false;
            foreach (var g in groups)
            {
                series.Points.AddXY(g.Key, g.Count());
                hasPoints = true;
            }

            series.IsValueShownAsLabel = true;
            series.ToolTip = "#VALX";

            if (hasPoints)
                chart.DataManipulator.InsertEmptyPoints(1, IntervalType.Days, series);
        }


        area.AxisX.LabelStyle.Format = "ddd M/d";
        return new ChartResult(chart);
    }

Как я могу удалить


person Carl Raymond    schedule 25.05.2011    source источник


Ответы (3)


У меня есть способ заставить это работать.
Извините за длинный ответ, но я обнаружил, что способ, которым вы пытаетесь реализовать этот ответ, повлияет на то, сработает он или нет.

Вам нужно установить точку на ноль вручную, когда вы добавляете точки. Примечание. Мне не удалось выполнить эту работу, добавив нулевые точки постфактум.

См. следующие примеры и полученные снимки экрана: chart1.Series.Clear(); chart1.Series.Add(новая серия()); chart1.Series.Add(новая серия()); chart1.Series.Add(новая серия()); chart1.Series.Add(новая серия());

foreach (Series s in chart1.Series)
{
    s.ChartType = SeriesChartType.StackedColumn;
}

//chart1.Series[0].Points.Add(new DataPoint(0, 0));
chart1.Series[0].Points.Add(new DataPoint(1, 3));
chart1.Series[0].Points.Add(new DataPoint(2, 3));
chart1.Series[0].Points.Add(new DataPoint(3, 3));

chart1.Series[1].Points.Add(new DataPoint(0, 3));
//chart1.Series[1].Points.Add(new DataPoint(1, 0));
chart1.Series[1].Points.Add(new DataPoint(2, 3));
chart1.Series[1].Points.Add(new DataPoint(3, 3));

chart1.Series[2].Points.Add(new DataPoint(0, 3));
chart1.Series[2].Points.Add(new DataPoint(1, 3));
//chart1.Series[2].Points.Add(new DataPoint(2, 0));
chart1.Series[2].Points.Add(new DataPoint(3, 3));

chart1.Series[3].Points.Add(new DataPoint(0, 3));
chart1.Series[3].Points.Add(new DataPoint(1, 3));
chart1.Series[3].Points.Add(new DataPoint(2, 3));
//chart1.Series[3].Points.Add(new DataPoint(3, 0));

chart1.SaveImage("C:\\Before.png", ChartImageFormat.Png);

Изображение «before.png»: введите здесь описание изображения

Теперь удалите комментарии для ряда без точек данных при заданном значении x:

(Примечание! Я обнаружил, что это не работает, если вы добавляете точки с заданным значением x для значений, где вы делаете y = 0 в конце, то есть прямо перед сохранением изображения. Порядок точек в ряду имеет значение. для StackedColumn я никогда не работал с этим типом, за исключением того, что изучал, как ответить на этот вопрос, так что это может быть общеизвестно для пользователей этого типа)

chart1.Series.Clear();
chart1.Series.Add(new Series());
chart1.Series.Add(new Series());
chart1.Series.Add(new Series());
chart1.Series.Add(new Series());

foreach (Series s in chart1.Series)
{
    s.ChartType = SeriesChartType.StackedColumn;
}

chart1.Series[0].Points.Add(new DataPoint(0, 0));
chart1.Series[0].Points.Add(new DataPoint(1, 3));
chart1.Series[0].Points.Add(new DataPoint(2, 3));
chart1.Series[0].Points.Add(new DataPoint(3, 3));

chart1.Series[1].Points.Add(new DataPoint(0, 3));
chart1.Series[1].Points.Add(new DataPoint(1, 0));
chart1.Series[1].Points.Add(new DataPoint(2, 3));
chart1.Series[1].Points.Add(new DataPoint(3, 3));

chart1.Series[2].Points.Add(new DataPoint(0, 3));
chart1.Series[2].Points.Add(new DataPoint(1, 3));
chart1.Series[2].Points.Add(new DataPoint(2, 0));
chart1.Series[2].Points.Add(new DataPoint(3, 3));

chart1.Series[3].Points.Add(new DataPoint(0, 3));
chart1.Series[3].Points.Add(new DataPoint(1, 3));
chart1.Series[3].Points.Add(new DataPoint(2, 3));
chart1.Series[3].Points.Add(new DataPoint(3, 0));

// If you add the empty points here, it does not seem to work.  
// Empty points are as follows, and are already added above in the 'after' example.
// chart1.Series[0].Points.Add(new DataPoint(0, 0));
// chart1.Series[1].Points.Add(new DataPoint(1, 0));
// chart1.Series[2].Points.Add(new DataPoint(2, 0));
// chart1.Series[3].Points.Add(new DataPoint(3, 0));

chart1.SaveImage("C:\\After.png", ChartImageFormat.Png);

Изображение «after.png»: введите здесь описание изображения

Итак, учитывая, что вы не можете добавить нулевые точки постфактум (хотя вы можете их вставить?), вам нужно будет изменить свой код примерно так:

var allPossibleGroups = t.StudentReports;

var groups = t.StudentReports
            .Where<StudentReport>(rep => rep.IsComplete && rep.FirstSaveTimestamp.HasValue)
            .GroupBy<StudentReport, DateTime>(rep => rep.FirstSaveTimestamp.Value.Date);

        bool hasPoints = false;
        foreach (var g in allPossibleGroups)
        {
            if(groups.ContainsKey(g))
            {
                series.Points.AddXY(g.Key, g.Count());
                hasPoints = true;
            }
            else
            {
                series.Points.AddXY(g.Key, 0);
            }
        }

Извините за длинные блоки кода, но пример был необходим, чтобы продемонстрировать, как заставить его работать, не попадая в ловушку добавления пустых точек (где y = 0) в конце, так как это не сработает.

Дай мне знать, если тебе еще понадобится помощь.

person JHubbard80    schedule 01.08.2011

Сам столкнулся с той же проблемой и хотел поделиться правильным решением:

Используйте DataManipulator, чтобы вставить недостающие значения (x, y):

foreach (Series s in chart.Series)
{
    chart.DataManipulator.Sort(PointSortOrder.Ascending, "X", s);
    chart.DataManipulator.InsertEmptyPoints(1, IntervalType.Number, s);
}
person Jason Orphanidis    schedule 22.10.2013
comment
Это фактически зафиксировало ширину столбцов для меня, но пробелы все еще есть. - person Eugene Pavlov; 20.05.2014

Цикл через серию по какой-то причине у меня не работает, но следующее решение работает как шарм:

Chart1.DataManipulator.InsertEmptyPoints(1, IntervalType.Number, "Series1, Series2, Series3, Series4")
person Eugene Pavlov    schedule 20.05.2014