Can't view designer when coding a form in C#
Asked Answered
A

2

8

I'm following this tutorial on winforms, and so far the tutorial is coding the form without using the toolbox. I believe it'll introduce the toolbox in more depth shortly.

Following the tutorial, I've made a partial class in the following two pieces of code:

First file:

using System;
using System.Windows.Forms;

public class Numeric : System.Windows.Forms.TextBox
{
    public Numeric()
    {
    }
}

public partial class Exercise
{
    private Numeric txtbox;
    System.ComponentModel.Container components;
}

Second file:

using System;
using System.Windows.Forms;

public partial class Exercise : Form
{
    private void InitializeComponent()
    {
        txtbox = new Numeric();
        Controls.Add(txtbox);
    }

    public Exercise()
    {
        InitializeComponent();
    }
}

public class program
{
    public static int Main()
    {
        Application.Run(new Exercise());
        return 0;
    }
}

When I run the code with F5, everything looks fine: The form pops up with the textbox.

But for some reason, when I right-click on the second file and choose "View Designer", I get an error which says "The variable 'txtbox' is either undeclared or was never assigned". I can choose to "Ignore and Continue", which leads me to a form with no textbox on it.

Why does this occur? I know some of you think I should just use the toolbox, and it's probably the most sensible thing to do, but I would still like to understand why this happens.

Ape answered 30/8, 2015 at 16:43 Comment(4)
You have to declare type of txtbox. Where is it? you cannot expect designer to show anything that happens in InitializeComponent()Apple
Are you using some third party controls? If yes, then it leads such issue you are facing.Lira
@Apple I declare the type of txtbox in the first file, and I thought that since the class was partial, it could find the type just fine.Ape
@Lira Ok, but I only use the standard controls.Ape
W
15

How does the Windows Forms Designer work?

When you open a Form in windows forms designer, the designer looks into the first class in the file. If the file has a Designer.cs containing the other partial part of the class, also includes it and tries to deserialize those file contents. In the process of deserialization and loading the design time of your form, it creates an instance of the base class of your form and looks in those files for component declarations and InitializeComponents method. If find them creates components and sets properties of them using deserialized codes and add components to the instance of base class which created.

Some useful facts:

  • Codes in constructor of your Form will not execute at design-time, but the constructor of base class of your form will execute in design-time.
  • Codes in InitializeComponent will not execute at design-time, but those codes will be deserialized and will be used to create designer of the form.
  • The designer can not show a form which has an abstract base class. (solution)
  • The designer can not show a form which has generic class. For example it can not show MyForm:SomeForm<SomeClass>, but it can show SomeForm<T>:Form. (solution)
  • If you define a new property for your form, the properties will not show in properties window. The properties window, shows the properties of base class but with values of your form.
  • When a file contains 2 class, if the form was not the first class the designer can not load and you receive a warning that says the form should be first class to show in designer.
  • Above rules will apply also to UserControls.

Example

Take a look at below code, which has some serious problems:

  • The class has different constructor than class name
  • The statement int i="x";
  • There is no semicolons while this is a C# class
  • The InitializeComponent method didn't call in constructor

But the interesting news is you can see the form in designer, even with those errors!

Just create a file in your project and put below codes in the file and save the file and close it. Then without trying to build the solution, open the form in designer. Here is code:

using System
using System.Windows.Forms
namespace SampleApplication
{
    public class MyForm:Form
    {
        public NotMyForm()
        {
        }
        public void InitializeComponent()
        {
            int i="x";
            textBox1 = new TextBox()
            textBox1.Text = "Hi"
            this.Controls.Add(textBox1)
        }
        private TextBox textBox1
    }
}

And here is screenshot of designer:

enter image description here

More information

To find more information, take a look at this link:

Solution for your question

As a solution, it is enough for you to move private Numeric txtbox; and put it your seccond file in Exercise class.

Womanish answered 30/8, 2015 at 18:16 Comment(2)
Thanks a lot! This somewhat makes sense to me. Am I right in the following understanding? When I ask VS to show the form, it doesn't compile anything; it only parses and deserializes (which seems to mean converting code to bytes), and thus even though my class is partial, it doesn't look at all at the other half of the class? The other half of the class is where I initialised "txtbox", but it doesn't see this. If I put everything inside the same (non-partial) class, I should have no problem with the designer.Ape
Yes you have a good understanding of what happens behind the scene. The designer somehow (using CodeDom serializers ) parse and converts your written code to instances of controls in memory and adds them to an instance of your base class and shows them on design surface.Womanish
P
1

The declaration of the controls should be put into Designer.cs files in order Visual Studio can just compile this unit and display it.

When you launch the app, the compiler takes into account all parts of your partial class then it finds txtBox declaration.

Try leave only the form class with its graphical declarations in a single file. This single file should have InitializeComponent methdod, construcutor and field declarations of UI components initialized in InitializeComponent().

Plutonium answered 30/8, 2015 at 16:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.