I have a Chart Control (System.Windows.Form.DataVisualisation.Charting, so WinForms) with multiple series, some are assigned to the primary, and some to the secondary Y-axis.
I need the chart to draw the series in a specific Z-order (meaning which series is drawn first, second, and so on), because some of them are overlapping. I can't find any related property.
I thought the z-order would depend on the order in which the series are added to the SeriesCollection, but this doesn't seem to change anything in my tests.
Am I missing something?
PS: It's not a 3D-Graph. So I am only asking about the order in which the different series are drawn.
The series are drawn in the order they are placed into the Chart.Series collection. Therefore you can automatically send new series to the back by using an Insert instead of an Add:
myChart1.Series.Add(myNewSeries1); // Draws this series on top of the others.
myChart1.Series.Insert(0, myNewSeries2); // Draw this series behind the others.
The following could be converted to an extension method for the chart control and (along with other methods e.g. BringToFront) could then be used in setting the order of series.
public void SendToBack(Series s)
{
if (myChart1.Series.Contains(s))
{
myChart1.Series.Remove(s);
myChart1.Series.Insert(0, s);
}
}
The series are drawn in the order in which they are added to the Chart.Series collection. Add the one you want drawn on top as the last element in the collection.
Related
I have generated a chart in asp.net c#, which gets user data from the database and display it. Now I want to add a line to it which can indicate the baseline set by the user. I think it might be a new series which will be drawn from start to end. It will be ideal if the user is able to change it and on changing the line is redrawn. I have dates on x-axis and activity time on y axis. In the following picture I want line like Goal. Any suggestions?
There are two ways I know which can be used to achieve this line.
One is by adding the tag but the line will appear under the bars.
If you want the line to appear above the bars then you need to add another series of type line chart. Make its x axis secondary and specify the values so that it appears as a straight line. Hide the lengends and labels etc for line chart.
I'm working on a LineGraph control which consists many DependencyProperties that affect how the control should display its data. For example, the control contains the following properties to affect its axes:
AxisStroke - Color of the axes.
AxisThickness - Stroke thickness of the axes.
It also contains properties for display numbers & tick marks
VerticalTicks - True/False to indicate whether or not ticks appear along the vertical axis
HorizontalTicks - True/False to indicate whether or not ticks appear along the horizontal axis
VerticalMin - Minimum value on the vertical axis (numeric)
VerticalStep - The distance in between each vertical tick
VerticalMax - Maximum value on the vertical axis (numeric)
HorizontalMin - Minimum value on the horizontal axis (numeric)
HorizontalStep - The distance in between each horizontal tick
HorizontalMax - Maximum value on the horizontal axis (numeric)
And many more properties exist to allow for different line styles on a single graph (LineColor, LineThickness, DataPointShape, and DataPointIcon to name a few).
My goal is to be able to call out my LineGraph in XAML to insert it into a Window. I would like to be able to specify each of these settings inside the XAML as well, and see the new rendered image of the control in the WPF designer.
Now, given there is a lot of geometric shapes to render on the LineGraph, I though using a Canvas would be a good choice to render the data. Unfortunately, when I'm working in XAML, I cannot perform computations for the locations of shapes based on the control's width & height.
And yes, the shapes' locations must be computed because the data points for the graph are dynamic and the tick-related information is dynamic. Not to mention, I would like to display the actual values along each axis of the LineGraph.
So, I thought I might be able to display this control as if I was doing the rendering in C# code. Other windowing frameworks sometimes provide a Render method that can be used for laying out all of the sub-components.
Doing this, however, doesn't seem possible since WPF relies heavily on XAML for the visual appearance of controls. Also, requiring that the WPF designer must display the LineGraph based on the properties and data specified, it doesn't seem like C# code would solve the problem.
I suppose my questions are these:
How can I render data dynamically inside of a WPF control?
Am I able to specify in C# how my control is rendered, allowing the WPF designer to reflect it?
Side Note:
I've done quite a bit of research, but I am only finding information on how to implement more simple types of controls. If you know of any references that contain information on this topic, please feel free to post them in addition to your answers. I will be more than happy to learn how to do this completely.
EDIT:
I've created a graph using Excel to elaborate what the LineGraph control might look like if it has correct data and properties.
I will answer this based on my experience on implementing custom built graphing libraries in WIN32, WinForm, WPF, WinCE, WP8+WinRT, ....and even on a FPGA :)
It's extremely difficult to implement one from scratch. It may seem easy at first but you will run into a lot of "What should I do if this happens?". For example, in your above graph it seems you got a DataPoint # (5,100) it graphs it pretty well. But lets say, I add another DataPoint # (5.000000005, 0). How would you handle that in your code? Would you say that each pixel on the graph represents an exact value on the X-Axis, or does each pixel represent a range of X-Values?
I would recommend that you use an already establish library to do what you want to do unless you need something very specific like lets say you need horizontal cursors on the graph (think Tektronix Oscilloscope) and you need to calculate some values in between the two cursors.. then maybe you need to implement your own custom one or build on top of an open source one.
So, if you are still adamant of creating your own custom control here are answers to your questions.
How can I render data dynamically inside of a WPF control?
You can use a WriteableBitmap and create your own primitive drawing library from that. After you're done rendering, set it as the ImageSource of your control.
Or you can use WriteableBitmapEx which has GDI like drawing functions already implemented for you.
WriteableBitmapEx CodePlex Page, I also think you can just get it from NuGet as well.
You can also use a <Canvas> and add UI elements to that as well.
Am I able to specify in C# how my control is rendered, allowing the WPF designer to reflect it?
This depends on how you create your controls, but yes you can create Properties in your custom control that will appear in the Designer. Allowing you to change it thus updating the display. I would read a lot of tutorials about writing your own custom user control library. They can explain it better than I can in a SO answer. If you implement the properties correctly it should like so.....
Full Size Image: http://i.stack.imgur.com/pmevo.png
After changing the Number of Rows from 15 to 10 and the starting Y offset to -1 (thus moving the graph up and making the rows a lot taller)
Full Size Image: http://i.stack.imgur.com/0RKnA.png
Been struggling with this through out the day. I have three series on a chart that look like this. NOTE: I am using the winforms control.
The values are being added based on calculations from input. I am using this code to add the values to each series.
this.chart1.Series["green"].Points.AddY(greenvalue);
this.chart1.Series["totalsaving"].Points.AddY(totalsavingvalue);
this.chart1.Series["blue"].Points.AddY(bluevalue);
The series properties I have set like this. Green and totalsaving are both set to StackedColumn, blue is set to Column for chart type.
I then have a button to start over which brings the user back to the input area and I am then using this code to clear the series values on the start over click.
chart1.Series["totalsaving"].Points.Clear();
chart1.Series["green"].Points.Clear();
chart1.Series["blue"].Points.Clear();
The same calculation click is being used as above to calculate and populate the series data. The problem is when I click the calculate button to calculate the values after I have cleared them, the total savings, and the green are missing. Just the blue is shown.
Am I doing something wrong with the way I am trying to clear the values so I can re calculate?
OK, from the edits, comments, our chat and the joim.me session enough data has accumulated to answer the question.
You have twisted the display by adding an extra data point to the blue series in the designer.
This point occupies slot 1 but remains invisible as its value = 0.
This pushes the next point in the series to slot 2
After clearing the points it is gone and the display doesn't work anymore.
The disappearing of the two columns probably was caused by hard coded widths.
You have several paths you can follow:
recreating the extra point with value = 0 before adding the real data (not recommended)
not adding the extra point in the first place but forcing each point into its slot by using Points.AddXY instead of Points.AddY with X being the slot.
not clearing the points but updating their values by using the SetValueY method. After all three data points have beend assigned their new values you need to call chart1.Invalidate() to make it show.
Fore easiest styling of all those properties, some of which are deeply burried inside of property strings(!), you may even decide to add and style&polish all three points in the designer and only update their y-values like this:
chart1.Series["green"].SetValueY(greenvalue);
chart1.Series["totalsaving"].SetValueY(totalsavingvalue);
chart1.Series["blue"].SetValueY(bluevalue);
chart1.Invalidate();
The choice is yours, but in any case I recommend setting the proper X values, be it in code or in the desginer..
So, I am writing some text into a PDF file using iTextSharp.
After having added a few paragraphs and phrases to the PDF document, I want to:
Draw the next piece of text on top of a rectangle that has a fill color, say, red.
I can compute the required width and height that the rectangle must have based on the text metrics of the text I am going to write on top of it. But how do I tell the Rectangle API what is top and left coordinates are, as in where it must be drawn?
Seems that you are looking for the Chunk.setBackground() method. This draws a colored background underneath some text. There's also a variation of the method that takes extra parameters if you need a larger or smaller rectangle.
Suppose that you don't want a colored rectangle, but a custom type of shape, then you'd use the page event onGenericTag(). See Chunk > Generic tag for more info.
The onGenericTag() method is triggered every time a Chunk that is marked as generic (using the setGenericTag() method) is rendered to a page. Your implementation of the page event can then use the Rectangle value that is passed to the event method. It is important to understand that a single Chunk marked as a generic tag can result in multiple invocations of this method: if the contents of a single Chunk needs to be distributed over different lines, the event will be triggered as many times as there are lines (giving you a separate Rectangle value for every separate line).
I am creating a line graph using zedgraph which contains multiple lines and all of them are filled with labels displaying the data points. There are times when one of the lines is not visible at all but only the data point labels for that line are visible. I think this happens when the data is such that one line completely envelopes the other in terms of area covered and the order of rendering for the lines is such that the inner line is rendered before the container line. This I think is making the inner line invisible except for its data point.
So my question is:
How using zedgraph can I ensure that all portions of the filled curves along with their lines are rendered properly irrespective of their filled overlapping areas being subsets of each other and the order in which the curves are rendered?
How using zedgrapgh can I force the overlapping portions of the curves to display a fill color that is a resultant of the individual fill colors for the curves like in the chart image I found on google charts demo page below?
SOLVED!! - The only thing to do was add the alpha channel transparency to my line curve fills and everything else gets sorted automatically. Hope this helps someone.