[英]C# .NET Chart - Adding a legend scrollbar and checkboxes
我正在Visual Studio 2013中使用Chart類來可視化一些數據。 但是,我的數據很快產生了許多系列,將所有這些都放在一張圖表中非常重要。 我將圖例區域限制為整個圖表區域的20%,因此當我將圖表拉伸到最大大小時,我幾乎不能顯示超過7-8個圖例項。 該控件在圖例項目的空間用盡后才放入...。
而不是僅僅寫...,是否可以在圖例中添加滾動條並能夠查看所有項目? 我知道我可以通過某種方式實現自己的圖例,但我想從Chart類提供的內容中獲得最大的收益。 我還想在每個圖例項旁邊添加復選框,以指示該系列是否應該在圖表上隱藏。 如果沒有我自己的圖例實現,這有可能嗎?
另外,我還想在右鍵單擊圖例項目時擴展菜單,其中有幾個選項,但這是完全可選的。 滾動條和復選框是我現在的主要問題。
謝謝。
總體思路:您必須創建兩個圖表。 一個是主要的,第二個僅用於傳奇。 如果系列順序相同,您將具有相同的系列樣式。
要顯示彈出窗口,請右鍵單擊圖例項目:
將ContextMenu(工具箱中的ContextMenuStrip類)連接到圖例的圖表。
用於顯示圖例的隱藏系列:
您必須實現MouseClick
事件處理程序,並使用數學檢查鼠標光標下的對象( GetChildAtPoint()
方法不適用於圖例項目)。 公式:is series_index = control_relative_mouse_y / c_legendItemHeight
,其中c_legendItemHeight
是您提供的用於計算控件高度(單個圖例項的高度)的值。 您必須將圖例圖表配置為包含LegendStyle
到Row
, MaximumAutoSize
到100
, Docking
到Left
, IsTextAutoFit
為false
, IsEquallySpacedItems
為true
。 您在圖例中定義了3列(一列用於系列樣式,第二列用於復選框,第三列用於系列名稱)。 使用系列CustomProperties
保持可見性狀態。 在檢查列中,使用此自定義屬性(Text = "#CUSTOMPROPERTY(...)"
)顯示檢查狀態。 圖表不支持自動調整大小。 您可以手動執行。 在系列加載期間,將圖表高度設置為計算值。 此值等於_stock.Shares.Count * c_legendItemHeight + 9
。 其中: _stock.Shares.Count
是圖例中的項目數, c_legendItemHeight
項的高度恆定(整數值,數值大於18的數字似乎對我c_legendItemHeight
), 9
(似乎恆定)。 我知道這不好,但找不到更好的解決方案。 我在示例中添加了502系列,效果很好。 確保圖表中沒有任何邊距,否則將無法正確計算序列號。
對於“傳奇中的許多系列”問題:
將圖例圖表放到啟用了AutoScroll屬性的面板中。 使用上面描述中的表達式設置面板和圖例的高度。
源代碼:
public partial class Form1 : Form
{
private const int c_legendItemHeight = 20;
private const string c_checkCustomPropertyName = "CHECK";
private const string c_checkedString = "✔"; // see http://www.edlazorvfx.com/ysu/html/ascii.html for more
private const string c_uncheckedString = "✘";
private Stock _stock;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
_stock = Stock.Load();
// mainChart
mainChart.Legends.Clear();
foreach (Share share in _stock.Shares)
{
Series series = mainChart.Series.Add(share.Name);
series.ChartType = SeriesChartType.Line;
foreach (ShareQuotation shareQuotation in share.Quotations)
{
series.Points.AddXY(shareQuotation.Date.ToString(), shareQuotation.Close);
}
}
// LegendChart
Legend legend = legendChart.Legends[0];
legendChart.Series.Clear();
legend.IsTextAutoFit = false;
legend.IsEquallySpacedItems = true;
legend.MaximumAutoSize = 100;
legend.Docking = Docking.Left;
legend.LegendStyle = LegendStyle.Column;
legend.Position.Auto = true;
legend.Position.Width = 100;
legend.Position.Height = 100;
legend.CellColumns[1].Text = "#CUSTOMPROPERTY(" +c_checkCustomPropertyName+ ")";
foreach (Share share in _stock.Shares)
{
Series series = legendChart.Series.Add(share.Name);
series.SetCustomProperty(c_checkCustomPropertyName,c_checkedString);
}
legendChart.Height = _stock.Shares.Count * c_legendItemHeight + 9; // 9 - seems to be constant value
legendPanel.Height = legendChart.Height;
}
private void legendChart_MouseClick(object sender, MouseEventArgs e)
{
Point mousePosition = legendChart.PointToClient(Control.MousePosition);
int seriesNo = mousePosition.Y / c_legendItemHeight;
Series series = legendChart.Series[seriesNo]; // TODO - check if not out of range
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
// check uncheck series
if (series.GetCustomProperty(c_checkCustomPropertyName) == c_checkedString)
{
// if checked
// uncheck
series.SetCustomProperty(c_checkCustomPropertyName, c_uncheckedString);
series.CustomProperties = series.CustomProperties; // workaround - trigger change - is this a bug?
// hide in mainChart
mainChart.Series[seriesNo].Enabled = false;
}
else
{
// if unchecked
legendChart.Series[seriesNo].SetCustomProperty(c_checkCustomPropertyName, c_checkedString);
series.CustomProperties = series.CustomProperties; // workaround - trigger change - is this a bug?
// show in mainChart
mainChart.Series[seriesNo].Enabled = true;
}
}
}
private void contextMenu_Opening(object sender, CancelEventArgs e)
{
Point mousePosition = legendChart.PointToClient(Control.MousePosition);
int seriesNo = mousePosition.Y / c_legendItemHeight;
Series series = legendChart.Series[seriesNo]; // TODO - check if not out of range
contextMenu.Items.Clear();
string state = series.GetCustomProperty(c_checkCustomPropertyName) == c_checkedString ? "visible" : "hidden";
contextMenu.Items.Add("&Some strange action for " + state + " item named " + series.Name);
contextMenu.Items.Add("&Another action ...");
}
}
結果應如下所示:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.