0

I believe I know the cause of this issue but I'm unsure how to fix it.

I am using WinForms with the MVP(model-view-presenter) approach.

I have an event which has a subscriber, this subscriber calls a method which opens a new instance of a form and draws rectangles on the form. The form should look like this:Design

Now to get this to work on any page, I plan on resizing the rectangle based on the size of the form. I receive the data from the user on a form previously filled out.

My subscriber looks like this:

private void ValidateFormBeforeDiagram(object sedner, OptionOneCheckedEventArgs e) {
            try {
                //Create variables
                int pagesUp = e.IsOptionOneChecked ? view.OptionOneAround : view.OptionTwoAround;
                int pagesAcross = e.IsOptionOneChecked ? view.OptionOneAcross : view.OptionTwoAcross;
                float pageWidth = e.IsOptionOneChecked ? view.PageSizeLength : view.PageSizeWidth;
                float pageLength = e.IsOptionOneChecked ? view.PageSizeWidth : view.PageSizeLength;


                ParametersToCreatePrintingDiagram parameters = new ParametersToCreatePrintingDiagram(view.SheetSizeAcross, view.SheetSizeAround,
                    pagesUp, pagesAcross, pageWidth, pageLength);

                //Check if form is open, if so close it

                if (Application.OpenForms.OfType<PrintingDesignForm>().Any()) {
                    Application.OpenForms.OfType<PrintingDesignForm>().First().Close();
                }

                //Create a new instance of the form
                PrintingDesignForm form = new PrintingDesignForm();
                float ratio = 0;

                //If rectangle is larger than the client viewable size then scale the rectangle so it will fit.
                if (parameters.RectangleHeight > form.ClientRectangle.Height || parameters.RectangleWidth > form.ClientRectangle.Height) {
                    var ratioX = form.ClientRectangle.Height / parameters.RectangleHeight;
                    var ratioY = form.ClientRectangle.Width / parameters.RectangleWidth;

                    ratio = Math.Min(ratioX, ratioY);

                    parameters.RectangleHeight = parameters.RectangleHeight * ratio - parameters.RectangleXPosition;
                    parameters.RectangleWidth = parameters.RectangleWidth * ratio - parameters.RectangleYPosition;
                }

                //Draw the main rectangle
                form.Paint += (se, pe) => {
                    var r = new Rectangle(parameters.RectangleXPosition, parameters.RectangleYPosition,
                        (int)Math.Round(parameters.RectangleWidth), (int)Math.Round(parameters.RectangleHeight));

                    var brush = new SolidBrush(Color.FromArgb(255, 255, 204));

                    pe.Graphics.FillRectangle(brush, r);
                    using (var pen = new Pen(brush.Color, 2))
                        pe.Graphics.DrawRectangle(pen, r);
                };

                int leftXInches;
                int topYInches;
                int xInch = 0;
                int yInch = 0;
                List<Rectangle> rectArr = new List<Rectangle>();

                //Calculate the smaller rectangle sizes and positions
                for (int i = 1; i < parameters.PagesUp; i++) {
                    for (int j = 1; j < parameters.PagesAcross; j++) {
                        if (e.IsOptionOneChecked) {
                            leftXInches = (int)Math.Round(parameters.RectangleXPosition
                            + ((view.SheetSizeAcross - (view.PageSizeLength * view.OptionOneAcross) - (view.OptionOneAcross - 1) * view.Bleeds) / 2)
                            + ((j - 1) * parameters.PageWidth)
                            + ((j - 1) * view.Bleeds));

                            topYInches = (int)Math.Round(parameters.RectangleYPosition
                            + ((view.SheetSizeAround - (view.PageSizeLength * view.OptionOneAround) - (view.OptionOneAround - 1) * view.Bleeds) / 2)
                            + ((i - 1) * parameters.PageHeight)
                            + ((i - 1) * view.Bleeds));

                        }
                        else {

                            leftXInches = (int)Math.Round(parameters.RectangleXPosition
                         + ((view.SheetSizeAcross - (view.PageSizeWidth * view.OptionTwoAcross) - (view.OptionTwoAcross - 1) * view.Bleeds) / 2)
                         + ((j - 1) * parameters.PageWidth)
                         + ((j - 1) * view.Bleeds));

                            topYInches = (int)Math.Round(parameters.RectangleYPosition
                         + ((view.SheetSizeAround - (view.PageSizeLength * view.OptionTwoAround) - (view.OptionTwoAround - 1) * view.Bleeds) / 2)
                         + ((i - 1) * parameters.PageHeight)
                         + ((i - 1) * view.Bleeds));
                        }

                        var width = (int)((Math.Round(parameters.PageWidth) * 72) * ratio);
                        var height = (int)((Math.Round(parameters.PageHeight) * 72) * ratio);

                        yInch = (int)Math.Round((topYInches * 72) * ratio);

                        //Increase the xInch every loop as you need to make sure that there is room for other rectangles
                        if (j == 1) {
                            xInch = (int)Math.Round((leftXInches * 72) * ratio);
                        }
                        else {
                            xInch += width + 20;
                        }

                        //Add rectangle with specs ready to be painted onto the form
                        rectArr.Add(new Rectangle(xInch, yInch, width, height));
                    }
                }

                //Paint the smaller rectangles onto the form
                for (int i = 0; i < rectArr.Count; i++) {
                    form.Paint += (se, pe) => {
                        var r = rectArr[i]; //Exception occurs on this line

                        var brush = new SolidBrush(Color.FromArgb(255, 0, 0));

                        pe.Graphics.FillRectangle(brush, r);
                        using (var pen = new Pen(brush.Color, 2))
                            pe.Graphics.DrawRectangle(pen, r);
                    };
                }

                form.Show();
            }
            catch (Exception ex) {
                LogErrorToView(this, new ErrorEventArgs(ex.Message));
            }
        }

I have commented above where the exception occurs. It happens because after this class has run its course, the publisher event is completed. After this happens the two other paint events get called and it errors because rectArr is no longer in scope.

Is there any way I can fix this?

EDIT: Why the downvote?

Andrew
  • 720
  • 3
  • 9
  • 34
  • 2
    looks like the good old [closure misunderstanding](http://stackoverflow.com/a/227833/1132334). the value of `i` is evaluated post-loop. use a debugger to prove that it equals `rectArr.Count` by the time the `Paint` events are processed. Pass a copy of the rectangle to the closure to fix. – Cee McSharpface May 14 '17 at 23:29
  • Ahhh yes. Thank you very much, I've had this issue for the last couple days and you just helped me solve it. If you want to post this comment as an answer, I will select it as the chosen answer if you want :) – Andrew May 14 '17 at 23:44

0 Answers0