1

I have a specific user control with several properties, including one which is of another class. That class contains a public int[,] this[int x, int y] (I don't remember the exact term for that) as well as a public int[,] property and a private int[,] field. I then have a form containing that control. Whenever I attempt to edit the form and then save, it denies me from saving with the following popup appearing 3 to 6 times in a row:

Exact error message (obtained with control+c on the window):

---------------------------
Microsoft Visual C# 2010 Express
---------------------------
Array rank '2' is too high.  Visual Studio can only save and load arrays with a rank of 1.
---------------------------
OK   
---------------------------

Note that I don't need the information saved into these arrays in the designer; the value is set to a default each time anyways within the ExampleControl. I don't even have the ability to modify or see these arrays.


Here's all of the code needed to reproduce:

Create a new form application, and then delete the Form1.cs file generated.

Program.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace ArrayRankIssue
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main() {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new ExampleForm());
        }
    }
}

ExampleClass.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ArrayRankIssue
{
    public class ExampleClass
    {
        private int[,] data = new int[2, 2];

        public int[,] Data {
            get {
                return data;
            }
            set {
                if (value.GetLength(0) != data.GetLength(0) || value.GetLength(1) != data.GetLength(1)) {
                    throw new ArgumentException("Argument must match size of array exactly.");
                }
                data = value;
            }
        }

        public int[,] this[int x, int y] {
            get {
                return data;
            }
            set {
                if (value.GetLength(0) != data.GetLength(0) || value.GetLength(1) != data.GetLength(1)) {
                    throw new ArgumentException("Argument must match size of array exactly.");
                }
                data = value;
            }
        }
    }
}

ExampleControl.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ArrayRankIssue
{
    public partial class ExampleControl : UserControl
    {
        internal ExampleClass example = new ExampleClass();

        public ExampleClass Example {
            get {
                return example;
            }
            set {
                example = value;
            }
        }

        public ExampleControl() {
            InitializeComponent();
        }
    }
}

ExampleControl.Designer.cs:

namespace ArrayRankIssue
{
    partial class ExampleControl
    {
        /// <summary> 
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary> 
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing) {
            if (disposing && (components != null)) {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Component Designer generated code

        /// <summary> 
        /// Required method for Designer support - do not modify 
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent() {
            components = new System.ComponentModel.Container();
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        }

        #endregion
    }
}

ExampleForm.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ArrayRankIssue
{
    public partial class ExampleForm : Form
    {
        public ExampleForm() {
            InitializeComponent();
        }
    }
}

ExampleForm.Designer.cs:

namespace ArrayRankIssue
{
    partial class ExampleForm
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing) {
            if (disposing && (components != null)) {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent() {
            ArrayRankIssue.ExampleClass exampleClass8 = new ArrayRankIssue.ExampleClass();
            this.exampleControl1 = new ArrayRankIssue.ExampleControl();
            this.SuspendLayout();
            // 
            // exampleControl1
            // 
            this.exampleControl1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            this.exampleControl1.Example = exampleClass8;
            this.exampleControl1.Location = new System.Drawing.Point(12, 12);
            this.exampleControl1.Name = "exampleControl1";
            this.exampleControl1.Size = new System.Drawing.Size(150, 150);
            this.exampleControl1.TabIndex = 0;
            // 
            // ExampleForm
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(292, 273);
            this.Controls.Add(this.exampleControl1);
            this.Name = "ExampleForm";
            this.Text = "Form1";
            this.ResumeLayout(false);

        }

        #endregion

        private ExampleControl exampleControl1;
    }
}

After creating all of these files, select Build-->Rebuild solution [note 1]. Then, double-click ExampleForm.cs, click on the outlined control, and then press left and then right on your keyboard [note 2]. Then, press Control and S, and you will be greeted with the same error message many times.


What I'm looking for is a way to keep this message from popping up (and hopefully to solve the reason why it is popping up, not just suppress it). I have found a simple workaround, which is to close the form designer window and then save, but that seems impractical. Once it is successfully saved, the form appears properly, so there also doesn't seem to be any other effects.

The one other mention of this error message was in this question, but that offered no useful solution.


Note 1: This option is only available in "Expert mode" - if you don't have it, go to Tools-->Settings-->Expert Settings)
Note 2: This is needed so that the file appears as modified by Visual Studio. If it isn't done, you can't force a second save.

Community
  • 1
  • 1
Pokechu22
  • 4,984
  • 9
  • 37
  • 62

1 Answers1

1

Moving these lines worked for me:

From ExampleForm.Designer.cs:

ArrayRankIssue.ExampleClass exampleClass2 = new ArrayRankIssue.ExampleClass();
this.exampleControl1.Example = exampleClass2;

To ExampleForm.cs:

  public partial class ExampleForm : Form
  {
    public ExampleForm()
    {
      InitializeComponent();
      ArrayRankIssue.ExampleClass exampleClass2 = new ArrayRankIssue.ExampleClass();
      this.exampleControl1.Example = exampleClass2;
    }
  }

Solution 2 If you're properties are already setup and you don't need to change them mark them with:

[ReadOnly(true)]
[Browsable(false)]

In your example add those attributes to Data and this in ExampleClass.cs.

You'll have to change your code, remove any existing controls from your form, compile then re-add

MikeH
  • 4,242
  • 1
  • 17
  • 32
  • Ok, but that doesn't seem like the most permanent solution. Each time I add something to ExampleForm, I will need to put that there. But that is useful information. Although, I've already initialized the `exampleControl1.Example` in the class itself (`internal ExampleClass example = new ExampleClass();`). Odd that it is requiring it. I'll wait a bit and see if there's a better solution, and if none comes I'll mark this as accepted. – Pokechu22 Oct 31 '14 at 22:17
  • I *think* the problem here is that VS can't save information in your arrays. I don't know if you actually need the IDE to save info in these arrays, if you do you'll need to make some fundamental changes. – MikeH Oct 31 '14 at 22:21
  • I don't need it to save info into the arrays. The arrays are at a preset value. – Pokechu22 Oct 31 '14 at 22:22
  • @MikeHL That seems to have solved it. Though just to make sure, adding `[ReadOnly(true)]` doesn't actually prevent me from editing it in my main code using the `set` method, right? – Pokechu22 Oct 31 '14 at 22:44
  • No, it shouldn't. From [MSDN](http://msdn.microsoft.com/en-us/library/system.web.ui.design.controldesigner.readonly(v=vs.110).aspx): "Gets or sets a value indicating whether the properties of the control are read-only at design time." Therefore the attribute only affects design time. – MikeH Oct 31 '14 at 22:50