Home > other >  New panel not opening on Windows Form after triggering click event
New panel not opening on Windows Form after triggering click event

Time:10-19

I have a Windows Forms App. I created a custom UserControl which extends Panel. Inside one of my Forms, there is a button which should open that panel when clicked.

However, after clicking, I still don't see the panel displayed on the form.

Form code

public partial class IngredientMenu : Form
    {
        public IngredientMenu()
        {
            InitializeComponent();
        }

        private void btnOpenRegisterBasePanel_Click(object sender, EventArgs e)
        {
            BaseIngredientPanel baseIngredientPanel = new BaseIngredientPanel();
            baseIngredientPanel.Location = new Point(257, 63);
            baseIngredientPanel.Show();
            baseIngredientPanel.BringToFront();
            Console.WriteLine("panel should open");
            Console.WriteLine(baseIngredientPanel.Visible);
            Console.WriteLine(baseIngredientPanel.Location);
        }
    }

Panel code

public partial class BaseIngredientPanel : UserControl
    {
        public BaseIngredientPanel()
        {
            InitializeComponent();
        }

        private void btnRegisterBaseIngredient_Click(object sender, EventArgs e)
        {
            IngredientContext ingredientContext = new IngredientContext();
            if (ingredientContext.RegisterIngredient(txtName, txtUnit, lblBaseIngredientNameValidation, lblBaseIngredientUnitValidation))
            {
                MessageBox.Show("Ingredient Registered."
                        , "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
                txtName.Text = "";
                txtUnit.Text = "";
            }
            else
            {
                MessageBox.Show("There are errors in the form fields."
                        , "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void BaseIngredientPanel_Load(object sender, EventArgs e)
        {
            Console.WriteLine("I AM OPEN");
        }
    }

Additionally, the "I AM OPEN" message never appears, even after clicking, so it seems like in general it's not even loading the control.

How can I make the panel open after clicking a button? I'd rather not manually drag a panel into the designer since I need to have like 5 panels and designer is just gonna try to box them like a russian doll.

CodePudding user response:

All UI controls need to have a parent to whom they belong via the Controls.Add() method. The parent can be a Form or other controls (not all will accept children). e.g. Your panel can be the parent of textboxes, comboboxes, labels, etc.

private void btnOpenRegisterBasePanel_Click(object sender, EventArgs e)
{
    BaseIngredientPanel baseIngredientPanel = new BaseIngredientPanel();
    baseIngredientPanel.Location = new Point(257, 63);

    //Add user panel to form.  
    this.Controls.Add(baseIngredientPanel);

    //You will probably not need these two rows any more.  Try it out!  But make sure your usercontrol has Visible = true.
    baseIngredientPanel.Show();
    baseIngredientPanel.BringToFront();
}

Edit:

to answer your questions in the comment below

If you need to make many UI changes at the same time then it is also best to use this.SuspendLayout() and this.ResumeLayout() to temporarily suspend the UI logic. This will help with performance in such cases. See https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.control.suspendlayout?view=windowsdesktop-5.0 for more details

If you will need to remove the controls at some stage after adding them then you have two options.

  1. Create a separate List<BaseIngredientPanel> to (also) store your controls when adding them to the form. This use this list to find and remove them via this.Controls.Remove() method
  2. Give your BaseIngredientPanel a unique Name when creating it, and use this to find and remove the control via the this.Controls.Remove() method. All Controls already have a Name property so you can use this.

CodePudding user response:

If you want to show a Form, the class should be derived from Form. Your BaseIngredientPanel is not a Form, it is a UserControl.

UserControls are similar to other Controls like Buttons, ComboBoxes, Menus, DataGridViews, etc. Usually you use Visual Studio Designer to show them on a Form. In rare occassions you do this programmatically.

I created a custom UserControl which extends Panel.

What do you really want:

  • I want to create a special kind of Panel, one that behaves like a standard Panel, with only small differences. Users of my class may use almost all Properties of my special Panel: Derive from class Panel
  • I want to create a special kind of Panel, one that behaves like a standard Panel. I want to control which methods users of my special Panel can call: Create a class derived from UserControl and put a Panel on it.
  • I want to create a Form, on which I want to put a Panel. This Panel has some behaviour which I only use on this Form.

If you want to create a special kind of Panel, one that is to be reused on several Forms, use derivation. Whether you derive from Panel or UserControl depends on how fool proof you want your class to be, and how many Panel methods users of your class may call.

If your special Panel is only to be used on one Form, don't bother to create a special Panel class. Create a Form that contains the Panel.

Use standard Panel on special Form

If you decided that you don't have to reuse the behaviour of this Panel, you can just put it on a new Form. Use visual studio designer to Create the form and put a Panel on it. Subscribe to the Panel events that you want to react on.

If you want that the form also has a Button, also use visual studio designer to add the Button and subscribe to event Button_Clicked.

To show the PanelForm, you have to decide whether the PanelForm is model or modeless.

  • Modal: the operator can only use this Form until it is closed. He can't use other forms of this application. This is by far the most used kind of Form: on menu selection, or button click: show the PanelForm, use the PanelForm, close the PanelForm, after which the parent form can read the results of the PanelForm and act accordingly. Modal Dialog boxes are shown using Form.ShowDialog.
  • Modeless: while the PanelForm is shown, the operator can switch back to the parent form and interact with it. This is not used very often. You can use it to show some extra information about the status of the parent window or application, for instance the position of the mouse, or the selected Shape that you will draw. A modeless Dialog box is shown using Form.Show(). Keep in mind, that before you close the parent form, you will have to close the modeless dialog box

Show Modal

A good example is the OpenFileDialog form

In your parent form:

using (var form = new OpenFileDialog())
{
    // set properties of the OpenFileDialog before showing
    form.InitialDirectory = this.GetInitialDirectory();
    form.DefaultExt = ".txt";
    ...

    // Show the Form as a modal box and wait until it is Closed
    DialogResult dialogResult = form.ShowDialog(this);

    // the operator has closed the form. Interpret the result:
    if (dialogResult == DialogResult.OK)
    {
        string fileName = form.FileName();
        this.OpenFile(fileName);
    }
}

Modeless: operator can switch back to this form

private MyPanel PanelForm {get; set;} = null;

private void ShowMyPanel()
{
    if (this.PanelForm != null) return;   // panel already shown

    this.PanelForm = new MyPanel();

    // set properties:
    this.PanelForm.DisplayedItems = ...

    // show the PanelForm
    this.PanelForm.Show();
}

The operator can switch back to this form, and probably close this form. In that case you will have to Close the PanelForm:

private void CloseMyPanel()
{
    if (this.MyPanel != null)
    {
        this.MyPanel.Close();
        this.MyPanel.Dispose();
        this.MyPanel = null;
    }
}

private void OnFormClosing(object sender, ...)
{
    // if MyPanel is shown, is it allowed to Close this form AND myPanel
    // or should you warn the operator to close MyPanel first?

    if (this.MyPanel != null)
    {
         this.CloseMyPanel();     // close immediately

         // or:
         MessageBox.Show(..., "Please close Panelbox first");
    }
}

Of course you should also react if the operator closes the panelbox. Before showing the panel box:

this.MyPane.Closed  = OnMyPanelClosed;

private void OnMyPanelClosed(object sender, ...)
{
    if (object.ReferenceEquals(sender, this.MyPanel)
    {
        // my panel is closed
        this.MyPanel = null;

You can't dispose the Panel, because it is still being used. The Panel show Dispose itself when Closed.

Special Panel Class

If you have a Special Panel Class (derived from either Panel, or UserControl), then after compiling, the panel control is visible in the toolbox of visual studio designer.

You should use use visual studio designer to create a Form and put the panel on the Form:

class MyPanelForm : Form
{
    public MyPanelForm()
    {
        InitializeComponent();

If you have used visual studio designer to add the special Panel, then you will find it in InitializeComponent. You can also add it yourself in the constructor. In that case, don't forget to add it to this.components, so your panel will be disposed when MyPanelForm is disposed.

To show MyPanelForm, use either ShowDialog or Show, as described in the previous section.

  • Related