I cannot reproduce all you application (I don't have your data file, etc.).
First thing I can see with unarmed eye is the lack of invalidation.
Assuming your data is correct (lines are not out of bounds, not closed by other controls, etc.) your method of rendering should work, everything looks fine, except one thing: who said that
WM_PAIN
message (the only thing that fire your panel's
Paint
event) is sent at the moment our data used by
panel1_Paint
is set up?
Make one experiment: show your application the at the moment you expect your lines rendered. ALT+TAB your application away to be fully closed by some other window and activateit back. You may have two results:
#1. Lines appear => make sure you call
panel1.Invalidate()
after line data is ready -- it will fire
Paint
event. Later on, you may get better results calling
panel1.Invalidate()
with parameters to invalidate not full panel, but smaller region or rectangle.
#2. Lines did not appear => Set a breakpoint inside
panel1_Paint
and under debugger examine coordinate of each line, compare them with panel bounds, make sure lines are not hidden under some other controls, etc.
By the way, this
panel1.Paint += new PaintEventHandler(panel1_Paint);
is a stone-age syntax used by Microsoft because they don't want to re-write code auto-generation (I would understand them).
Better manually write:
panel1.Paint += (sender, eventArgs) => {
Graphics g = eventArgs.Graphics;
Pen myPen = new Pen(System.Drawing.Color.Red, 5);
g.DrawLine(myPen, ...);
g.DrawLine(myPen, ...);
};
The code above is using lambda form not available in older C# versions. For C# v.2 a different syntax should be used:
panel1.Paint += delegate(object sender, PaintEventArgs eventArgs) { };
The supportability of the code is greatly improved if you stop adding event handlers in design-time. In this case, this code (setting up of the event handler to anonymous method in lambda form) anywhere to be called before first Paint
event, in practice before showing of the form. Good place to set up all event handlers for the form and its component is right after InitializeComponent();
(normally auto-generated in the form constructor).
There are many benefits: you don't have to write down exact profile with exact types of event arguments (type inference helps). You can place whole code of the handler right in the block (as it is shown above), but you can also make it a single call to a separate method, but now this separate method does not have to be of exact same profile as the delegate (for example, sender
is rarely used, and event arguments parameter sometimes is not used), so the dead parameter are removed which simplified the code.
The code becomes more observable and controllable. You can place setting up of the handler (with +=
operator) and the body of handler together or close, or at your convenience. You can better isolate auto-generated code from your own (I usually create yet another separate file with with yet another declaration public partial class
of the same form) -- many improvements.