I have questions about the MS ASP.NET chart control.
How can a line series be set over a bar series so that it extends to the y-axis of a chart?
Is it possible to place the name of the line series, i.e. "Goal", to the right of the chart as a replacement to including this series in the legend?
As you can see in the screenshot below, I have a line series presenting on top of a bar series that doesn't extend to the y-axis of the chart.
The code is as follows:
var data1 = new Dictionary<string, float>
{
{ "W1", 80},
{ "W2", 60},
{ "W3", 40},
{ "W4", 20},
{ "W5", 10}
};
var data2 = new Dictionary<string, float>
{
{ "W1", 10},
{ "W2", 10},
{ "W3", 0},
{ "W4", 10},
{ "W5", 10}
};
var data3 = new Dictionary<string, float>
{
{ "W1", 10},
{ "W2", 30},
{ "W3", 50},
{ "W4", 70},
{ "W5", 80}
};
var data4 = new Dictionary<string, float>
{
{ "W1", 50},
{ "W2", 50},
{ "W3", 50},
{ "W4", 50},
{ "W5", 50}
};
var chart = new Chart();
chart.Height = Unit.Pixel(300);
chart.Width = Unit.Pixel(450);
chart.Legends.Add("Legend").Alignment = StringAlignment.Center;
chart.Palette = ChartColorPalette.None;
chart.PaletteCustomColors = new Color[] { Color.FromArgb(191, 214, 151), Color.FromArgb(249, 255, 149), Color.FromArgb(191, 79, 75), Color.Green };
var area = new ChartArea();
area.AxisX.MajorGrid.LineColor = Color.Transparent;
chart.ChartAreas.Add(area);
var series1 = new Series("Done");
foreach (var item in data1)
{
series1.Points.AddXY(item.Key, item.Value);
}
series1.MarkerBorderWidth = 1;
var series2 = new Series("In Progress");
foreach (var item in data2)
{
series2.Points.AddXY(item.Key, item.Value);
}
var series3 = new Series("Needs Review");
foreach (var item in data3)
{
series3.Points.AddXY(item.Key, item.Value);
}
var series4 = new Series("Goal");
foreach (var item in data4)
{
series4.Points.AddXY(item.Key, item.Value);
}
series4.ChartType = SeriesChartType.Line;
series4.BorderWidth = 2;
series1.ChartType = series2.ChartType = series3.ChartType = SeriesChartType.StackedColumn;
series1.Font = series2.Font = series3.Font = series4.Font = new Font("Verdana", 8.25f, FontStyle.Regular);
chart.Series.Add(series1);
chart.Series.Add(series2);
chart.Series.Add(series3);
chart.Series.Add(series4);
Thanks for the help.
UPDATE:
As I continue to search for an appropriate solution, I implemented an additional chart for just the "Goal" line series with the intentions of:
Setting the color of certain properties of this new chart to Transparent and
Laying this chart on top of the existing chart
This approach provided the correct presentation by displaying the "Goal" line series over the bar series and allowing the "Goal" line series to extend to the y-axis. But it disabled the tooltips and the click actions of the bar series on the existing chart. Due to this deficient user experience, this approach isn't a suitable solution.
The search for a solution continues...
For question 1:
Another way is to use the PostPaint event, where you can draw anything you wish, anywhere on the chart... but still you lose the tooltips and such interactive features with that line.
For your question 2:
You can exclude the unwanted legend entry from the legend item collection; you can customize legend like it is done this example:
yourChart.CustomizeLegend += new EventHandler<CustomizeLegendEventArgs> (CustomizeLegendEventHandler);
//...
static void CustomizeLegendEventHandler(object sender, CustomizeLegendEventArgs e)
{
int anotherIndex = 3;
if (sender != null && sender is Chart)
{
if (e != null && e.LegendItems != null && e.LegendItems.Count > 0)
{
Chart ch = ((Chart)sender);
if (...) //your logic here
{
//example: you can move a legend item from one index to another here:
LegendItem item = e.LegendItems[0];
e.LegendItems.RemoveAt(0);
e.LegendItems.Insert(anotherIndex, item);
}
}
}
}
And, you can have a secondary Y axis with only one label, one point, etc. or: you can use the PostPaint event handler to draw anything you wish.
You can download a great installable sample pack from MS: here. They show many code examples which you can study. I found out these things from those samples and from using this new free reflector: ILSpy.
Hope this helps.
Related
Hello everyone i working in project that convert data (date and value) to graphic curve .
i have problem with x axis the value of date printing in double format , i want this values showing like this format 14:12:35
var gradientBrush = new LinearGradientBrush
{
StartPoint = new System.Windows.Point(0, 0),
EndPoint = new System.Windows.Point(0, 1)
};
gradientBrush.GradientStops.Add(new GradientStop(System.Windows.Media.Color.FromRgb(33, 148, 241), 0.2));
gradientBrush.GradientStops.Add(new GradientStop(Colors.Transparent, 1));
cartesianChart1.Series.Add(new LineSeries
{
Values = GetData(),
Fill = gradientBrush,
StrokeThickness = 0.9,
PointGeometry = null
});
cartesianChart1.Zoom = ZoomingOptions.X;
private ChartValues<DateTimePoint> GetData()
{
var values = new ChartValues<DateTimePoint>();
for (var i = 0; i <lsTemp.Count(); i++)
{
// System.DateTime.Today.AddDays(i)
values.Add(new DateTimePoint(lsDataTime[i], lsTemp[i]));
}
return values;
}
enter image description here
you need to set LabelFormatter property of Axis class.
Something like this:
AxisX = new Axis
{
Title = "Date",
Separator = new Separator { IsEnabled = false,Step = 1 },
LabelsRotation = -90,
Foreground = new SolidColorBrush(Colors.Black),
LabelFormatter = value => new System.DateTime((long)value).ToString("t")
};
And look at this link for formats ToString data formats
I was trying to overlap two chart areas. They would share the same x values, but Y would have different values and scales.
Here is outcome of my code:
As you can see red series is not in alignment with green series.I was searching this site for answers, but couldn't find one that worked. Could someone explain me why they don't align?
Code:
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
namespace TestGraph
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
#region Data
// Creating first series
Series s1 = new Series();
s1.Name = "Values";
s1.ChartType = SeriesChartType.Column;
s1.XValueType = ChartValueType.DateTime;
s1.Color = Color.Green;
s1.BorderWidth = 2;
// Hard Coding test values
DataPoint[] values =
{
new DataPoint(new DateTime(2017, 8, 1).ToOADate(), 10),
new DataPoint(new DateTime(2017, 8, 2).ToOADate(), 11),
new DataPoint(new DateTime(2017, 8, 3).ToOADate(), 12),
new DataPoint(new DateTime(2017, 8, 4).ToOADate(), 13),
};
// Adding vales to s1
foreach (DataPoint p in values)
{
s1.Points.Add(p);
}
// Creating second series
Series s2 = new Series();
s2.Name = "Values 2";
s2.ChartType = SeriesChartType.Column;
s2.XValueType = ChartValueType.DateTime;
s2.Color = Color.Red;
s2.BorderWidth = 2;
// Hard Coding test values
DataPoint[] values2 =
{
new DataPoint(new DateTime(2017, 8, 1).ToOADate(), 0.1),
new DataPoint(new DateTime(2017, 8, 2).ToOADate(), -0.2),
new DataPoint(new DateTime(2017, 8, 3).ToOADate(), -0.7),
new DataPoint(new DateTime(2017, 8, 4).ToOADate(), 13),
};
// Adding vales to s2
foreach (DataPoint p in values2)
{
s2.Points.Add(p);
}
#endregion
#region Charts
// Initializing chart
Chart mainChart = new Chart();
ChartArea area = new ChartArea();
ChartArea area2 = new ChartArea();
Controls.Add(mainChart);
mainChart.Dock = DockStyle.Fill;
// Adding areas to mainChart
mainChart.ChartAreas.Add(area);
mainChart.ChartAreas.Add(area2);
// Adding series to areas
s1.ChartArea = area.Name;
s2.ChartArea = area2.Name;
mainChart.Series.Add(s1);
mainChart.Series.Add(s2);
// Aligning areas
// Overlapping area2 with area
area2.AlignmentStyle = AreaAlignmentStyles.All;
area2.AlignmentOrientation = AreaAlignmentOrientations.All;
area2.AlignWithChartArea = area.Name;
// Scale actualization
area2.RecalculateAxesScale();
area.RecalculateAxesScale();
// Defining Y scale
area2.AxisY.Maximum = 2;
area2.AxisY.Minimum = -2;
area2.BackColor = Color.Transparent;
// Disabling unnecessary graphics
area2.BackGradientStyle = GradientStyle.None;
area2.AxisX.IsMarginVisible = false;
area2.AxisX.LabelStyle.Enabled = false;
area2.AxisY.LabelStyle.Enabled = false;
area2.AxisX.Enabled = AxisEnabled.False;
area2.AxisY.Enabled = AxisEnabled.False;
// Resizing chart back to 100%
area.Position = new ElementPosition(0, 0, 100, 100);
#endregion
}
}
}
One of your chart has AxisX.IsMarginVisible set to true, the other to false, hence the mismatch.
However, if you are trying to plot overlapping series, why are you not adding them to the same chart area instead of going through all this trouble?
I'm trying to create a Line Graph with zed graph. I just wanted to ask that how can I create a Line Graph which XAxis type is text and YAxis type is doubles.
Firstly i was really searching about this topic but i didnt get any result about it. Because other Line graphs are always about date&time on XAxis. I don't need date&time on XAxis. I will use labels for XAxis to name points on YAxis .
Here an Example Graph
string[] labels = { "P(A)", "P(A)+P(T)", "P(A)+P(T)+P(G)", "P(A)+P(T)+P(G)+P(C)" };
double[] y = { PA(), PA() + PT(), PA() + PT() + PG(), PA() + PT() + PG() + PC() };
LineItem myLine = myPane.AddCurve("dizi 1", null, y, Color.Red);
myLine.Line.Fill = new Fill(Color.Red, Color.White, Color.Red);
myPane.XAxis.Scale.TextLabels = labels;
myPane.XAxis.Type = AxisType.Text;
myPane.Chart.Fill = new Fill(Color.White, Color.FromArgb(255, 255, 166), 90F);
myPane.Fill = new Fill(Color.FromArgb(250, 250, 255));
zedGraphControl1.AxisChange();
****Codes are above . Is there anything wrong ?****
I just figured it out!
Here is example codes to create a basic line graph!
private void button3_Click(object sender, EventArgs e)
{
// generate some fake data
double[] y = { 1, 2, 3, 9 ,1,15,3,7,2};
string[] schools = { "A", "B", "C", "D" ,"E","F","G","H","J"};
//generate pane
var pane = zg1.GraphPane;
pane.XAxis.Scale.IsVisible = true;
pane.YAxis.Scale.IsVisible = true;
pane.XAxis.MajorGrid.IsVisible = true;
pane.YAxis.MajorGrid.IsVisible = true;
pane.XAxis.Scale.TextLabels = schools;
pane.XAxis.Type = AxisType.Text;
//var pointsCurve;
LineItem pointsCurve = pane.AddCurve("", null, y, Color.Black);
pointsCurve.Line.IsVisible = true;
pointsCurve.Line.Width = 3.0F;
//Create your own scale of colors.
pointsCurve.Symbol.Fill = new Fill(new Color[] { Color.Blue, Color.Green, Color.Red });
pointsCurve.Symbol.Fill.Type = FillType.Solid;
pointsCurve.Symbol.Type = SymbolType.Circle;
pointsCurve.Symbol.Border.IsVisible = true;
pane.AxisChange();
zg1.Refresh();
this.Controls.Add(zg1);
}
I want to create a chart with this Library, I have created one but the text is pixelated so the feel is very ugly.
I'm passing this charts to a PDF file with iText Sharp to create a report.
Here is the code:
private static byte[] ObtenerBarraDoble(IList<ValorBarraDTO> valores)
{
var newColor1 = Color.FromArgb(187, 189, 191);
var newColor2 = Color.FromArgb(0, 138, 209);
using (var graficoPie = new Chart { Height = 200, Width = 600, RenderType = RenderType.BinaryStreaming })
{
var chartAreaPie = new ChartArea();
chartAreaPie.AxisX.LabelStyle.Format = "dd/MMM\nhh:mm";
chartAreaPie.AxisX.MajorGrid.LineColor = Color.White;
chartAreaPie.AxisY.MajorGrid.LineColor = Color.White;
chartAreaPie.AxisX.LabelStyle.Font = new System.Drawing.Font("Trebuchet MS", 2);
chartAreaPie.AxisY.LabelStyle.Font = new System.Drawing.Font("Trebuchet MS", 2);
graficoPie.ChartAreas.Add(chartAreaPie);
var serieNuevo = new Series("Cartera Actual")
{
ChartType = SeriesChartType.Column,
XValueMember = "label",
YValueMembers = "valor1",
Color = newColor1,
Legend = "Cartera Actual",
IsValueShownAsLabel = true,
};
graficoPie.Series.Add(serieNuevo);
var serie = new Series("Cartera Recomendada")
{
ChartType = SeriesChartType.Column,
XValueMember = "label",
YValueMembers = "valor2",
Color = newColor2,
Legend = "Cartera Propuesta",
IsValueShownAsLabel =true,
};
graficoPie.Series.Add(serie);
graficoPie.DataSource = valores;
return PdfHelper.ChartABinario(graficoPie);
}
}
Here is ChartABinario method:
internal static byte[] ChartABinario(Chart graficoPie)
{
using (var ms = new MemoryStream())
{
graficoPie.SaveImage(ms, ChartImageFormat.Png);
byte[] retorno = ms.ToArray();
return retorno;
}
}
This creates the chart and it's displaying it well, but the text is bad. What can I do to make that the text doesn't display pixelated letters?
I am using the ZedGraph control and want to fill one side of the graph function with some color and other side with other color.
PointPairList list1 = new PointPairList();
list1.Add(0, 4);
list1.Add(4, 0);
LineItem myCurve = myPane.AddCurve("y(n)", list1, Color.Red, SymbolType.Diamond);
//This filling bottom side.
myCurve.Line.Fill = new Fill(Color.White, Color.FromArgb(113, 255, 0, 0), 90F);
//How to fill the top side?
I'm not very clear on what you're asking - but hopefully the below will help. You said in comments
Can I fill some polygon area in Zedgraph?
So here's how...
var zed = new ZedGraph.ZedGraphControl { Dock = System.Windows.Forms.DockStyle.Fill };
var poly = new ZedGraph.PolyObj
{
Points = new[]
{
new ZedGraph.PointD(0, 0),
new ZedGraph.PointD(0.5, 1),
new ZedGraph.PointD(1, 0.5),
new ZedGraph.PointD(0, 0)
},
Fill = new ZedGraph.Fill(Color.Blue),
ZOrder = ZedGraph.ZOrder.E_BehindCurves
};
var poly1 = new ZedGraph.PolyObj
{
Points = new[]
{
new ZedGraph.PointD(1, 0),
new ZedGraph.PointD(0.25, 1),
new ZedGraph.PointD(0.5, 0),
new ZedGraph.PointD(1, 0)
},
Fill = new ZedGraph.Fill(Color.Red),
ZOrder = ZedGraph.ZOrder.E_BehindCurves
};
zed.GraphPane.AddCurve("Line", new[] { 0.0, 1.0 }, new[] { 0.0, 1.0 }, Color.Green);
zed.GraphPane.GraphObjList.Add(poly1);
zed.GraphPane.GraphObjList.Add(poly);
Results in
Hopefully this will point you in the right direction!
(Code in VB as requested via http://converter.telerik.com/ - no guarentee of the VB code working or even compiling!)