簡體   English   中英

C#中的堆積柱形圖

[英]Stacked Column Chart in C#

我正在嘗試設置我的程序,以便用戶可以顯示一個堆積柱形圖,該圖顯示每個部門中出現的拒絕類別的數量(例如,部門 1 中出現 5 個,部門 2 中出現 3 個,等等)。 我在網上環顧四周並自己嘗試了一下,但我似乎無法讓它工作。 如果有人能夠提供幫助,那就太棒了。

當用戶按下按鈕切換到堆積柱形圖時,圖表當前會做什么: 堆積柱形圖

代碼:

private void btnStacked_Click(object sender, EventArgs e)
    {
        charRejections.Series["RFR"].Enabled = false;

        charRejections.Series["Department 1"].Points.Clear();
        charRejections.Series["Department 1"].Enabled = true;

        charRejections.Series["Department 2"].Points.Clear();
        charRejections.Series["Department 2"].Enabled = true;

        charRejections.Series["Department 3"].Points.Clear();
        charRejections.Series["Department 3"].Enabled = true;
        {
            string connectiontring = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|\\Database1.mdb";
            DataConnection = new OleDbConnection(connectiontring);

            try
            {

                DataConnection.Open();
                OleDbCommand command = new OleDbCommand();
                command.Connection = DataConnection;
                string query1 = "SELECT COUNT(reject_category) as reject, reject_category FROM tblReject_test GROUP BY reject_category";
                command.CommandText = query1;


                OleDbDataReader reader = command.ExecuteReader();
                while (reader.Read())
                {
                    charRejections.Series["Department 1"].Points.AddXY(reader["reject_category"].ToString(), reader["reject"].ToString());
                    charRejections.Series["Department 2"].Points.AddXY(reader["reject_category"].ToString(), reader["reject"].ToString());
                    charRejections.Series["Department 3"].Points.AddXY(reader["reject_category"].ToString(), reader["reject"].ToString());
                }

                DataConnection.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error " + ex);
            }
        }

        this.charRejections.Series["Department 1"].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.StackedColumn;
        this.charRejections.Series["Department 2"].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.StackedColumn;
        this.charRejections.Series["Department 3"].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.StackedColumn;
    }

創建堆積圖很容易。 也就是說,如果你有正確的數據。

創建堆積圖很難。 也就是說,如果您沒有正確的數據。

有一條規則要遵循:所有系列中的數據都需要對齊才能進行堆疊!

這聽起來很簡單,但實際上比人們想象的要復雜得多。

在我們開始舉幾個例子之前,這里是簡單規則分解為的細節:

  • 規則 #1 對於任何系列中的每個x 值,您都需要在 **每個系列中有一個數據點。**

  • 規則 #2您的點需要按正確的順序排列,即 x 值升序

  • 規則 #3 為了讓您控制要顯示的點范圍和圖表的其他方面,所有 x 值都應該是數字

有關堆疊圖表的工作示例,請查看這篇文章 問題是“如何避免差距?” 但它真的歸結為“如何使堆疊正常工作?” .

請注意,該示例使用來自以代碼編寫的 DataSource 的數據。 像您一樣從數據庫中讀取它沒有真正的區別。

解決方案是添加虛擬點來填補空白。

這將是您的問題之一,因為您不能期望查詢中的數據是完整的。

要解決此問題,您可以將查詢更改為某些join以填補空白,或者請圖表幫助您。

我不會進入 SQL 選項,盡管它似乎是最自然的選項。 但是請注意,為了遵循規則#2,您需要在查詢中添加一個order子句, order在任何情況下都按 x 值對記錄進行排序,即按您的拒絕類別。

讓我們來看看一個有趣的輔助函數Chart.DataManipulator.InsertEmptyPoints

這個函數有幾個重載; 我們將使用包含我們想要對齊的所有系列名稱的字符串的字符串。 這不僅會添加缺失的點,而且實際上將它們插入到缺失的位置,所以我們現在應該按照規則 #1 和 2 確定!

在進入更多細節之前(是的,更多細節,嘆息,但只是有很多地方要正確......)讓我們看看規則#3:

這是一種適用於所有圖表類型的圖表,也是圖表控件用戶最常中斷的一種規則,通常甚至沒有注意到..:

所有 X 值都應該是數字!

如果改為添加字符串,則這些字符串將被填充到軸標簽中,否則將被丟棄 最值得注意的是,結果數據點的 x 值都是0

只要您不需要它們就可以,但是一旦您使用它們,您就會遇到令人討厭的驚喜。 由於它們已經消失,您不能使用它們來計算它們的任何內容,或格式化標簽,或顯示工具提示等,或使用它們來設置要​​顯示的范圍。

請注意,即使 x 值都為0 ,數據點仍沿 x 軸分布; 你只是不再控制它了..

所以你需要決定一些方案來把你的 x 值變成數字!

一種是建立一個數據結構,其中列出了所有值:

 List<string> catLookup = new List<string>() { "ARTEFACT", "et..cetc.."};

然后,您可以像這樣找到每個值:

 int found = catLookup.FindIndex(x => x == someValueWeSearch);

這會起作用,但如果您的應用程序是真實的,它應該能夠隨着數據增長; 所以你應該從數據庫中讀取所有可能的值。 如果設計得當,已經有一個查找表可以使用,使用它的鍵將是最自然的選擇。

如果不是,您仍然可以使用簡單的查詢讀取值:

Select distinct reject_category from tblReject_test order by reject_category;

現在讓我們調用對齊我們擁有的所有系列:

  string seriesNames = String.Join(",", seriesLookup.Keys);
  chart1.DataManipulator.InsertEmptyPoints(1, IntervalType.Number, seriesNames);

現在回到您的原始代碼以及您需要在那里做什么:

一方面,您的所有值都是字符串。 所以你應該把循環改成這樣:

while (reader.Read())
{
    string seriesName = reader[1].ToString();
    int seriesIndex   = seriesLookup.FindIndex(x => x == seriesName);
    string catName    = reader[2].ToString();
    int catIndex      = catLookup.FindIndex(x => x == catName);

    charRejections.Series[seriesName ].Points.AddXY(catIndex, 
                                              Convert.ToInt16((reader["reject"]));
}

您會注意到,我不僅插入了使調試變得更加容易的輔助變量,而且還進行了第二次查找以保存創建系列所需的部門並將點添加到各自的系列中。

我把創造這個留給你; 如果未找到類別或部門,還添加必要的檢查..

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM