2011-05-25 12 views
6

Używam biblioteki wykresów w .Net 4.0, aby utworzyć skumulowany wykres kolumnowy z kilkoma seriami. Moim celem jest histogram, który pokazuje łączną liczbę działań (uzupełnień raportów) dziennie w kilku seriach (nauczycieli). Często brakuje danych (brak aktywności tego dnia przez konkretnego nauczyciela).Wykres kolumnowy Microsoft na wykresie ma luki

mam luki w barach gdy brakuje danych w serii:

Histogram with gaps in the columns

Mój kod:

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); 
    } 

Jak mogę usunąć

Odpowiedz

9

mam sposób, aby to zadziałało.
Przepraszam za długą odpowiedź, ale odkryłem, że sposób, w jaki spróbujesz wprowadzić tę odpowiedź, będzie miał wpływ, jeśli zadziała, czy nie.

Musisz ręcznie ustawić punkt na zero podczas dodawania punktów. Uwaga: Nie udało mi się wykonać tej pracy, dodając punkty zerowe po fakcie.

Zobacz przykłady i zrzuty ekranów: 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)); 

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

Obraz „before.png”: enter image description here

Teraz usunięcia komentarzy dla serii bez punktów danych przy danej wartości x:

(uwaga I okazało się, że nie robi działa, jeśli dodasz punkty o danej wartości x dla wartości, gdzie na końcu robisz y = 0 - także tuż przed zapisaniem obrazu. Kolejność punktów w serii wydaje się mieć znaczenie dla StackedColumn, nigdy nie pracowałem z ten typ, z wyjątkiem badania sposobu udzielania odpowiedzi na to pytanie, które może być powszechną wiedzą dla użytkowników tego typu)

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); 

Obraz „after.png”: (? Chociaż być może uda się je wstawić) enter image description here

więc, biorąc pod uwagę, że nie można dodać zero punktów po fakcie trzeba będzie zmodyfikować kod, aby coś takiego:

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); 
      } 
     } 

Niestety dla długich bloków kodu, ale przykład trzeba było wykazać jak zrobić to działa, bez popadania w pułapkę dodanie pustych punktów (gdzie y = 0) na końcu, ponieważ to nie zadziała.

Daj mi znać, jeśli potrzebujesz więcej pomocy.

+0

+1 dzięki za wspaniałe próbki kodu –

5

Ran na ten sam problem i chciał się podzielić właściwe rozwiązanie:

Zastosowanie DataManipulator wstawić brakujący (x, y) wartości:

foreach (Series s in chart.Series) 
{ 
    chart.DataManipulator.Sort(PointSortOrder.Ascending, "X", s); 
    chart.DataManipulator.InsertEmptyPoints(1, IntervalType.Number, s); 
} 
+0

Działa doskonale, dzięki. Również wciąż nie mam pojęcia, dlaczego tak się stało ... – Lambda

+0

To właściwie ustalona szerokość kolumn dla mnie, ale luki wciąż tam są. –

0

Looping thru serii nie pracują mnie z jakiegoś powodu, ale następne rozwiązanie działa jak urok:

Chart1.DataManipulator.InsertEmptyPoints(1, IntervalType.Number, "Series1, Series2, Series3, Series4") 
Powiązane problemy