none
winforms show everything in one form

    Question

  • Dear all.I am developing a winforms desktop application.I am trying to avoid a situation where a form pops up everytime a button is clicked.I then decided to use panels.What I want, is to have one form and a panel inside.create user controls and put them on the panel as needed.Just like the "Properties window in visual studio".I want to achieve an application, where only the details are changed.

    The problem I have is that the other user controls cannot see the panel.How can I make it public so that It can be accessed anywhere.

    e.g

    panel1.Controls.Clear();

    var myControl = new MmyControl(); panel1.Controls.Add(myControl);

    I want all my forms and user controls to be able to call panel.

    This is how I thought I would acheive what I wanted.It may not be the great choice.If you have any suggestions or alternatives, Please let me know, and I would be grfeatful to try that out.I would like to make this applications as user freindly as I can.

    • Moved by Mike Danes Monday, August 04, 2014 8:26 AM winforms related
    Monday, August 04, 2014 8:11 AM

Answers

  • As I already told you (?), you need to access the Panel of the already open instance of Form1:

    public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button2_Click(object sender, EventArgs e)
            {
                panel1.Controls.Clear();
                UserControl1 m = new UserControl1();
                panel1.Controls.Add(m);
            }
    
     //added property:
     public Panel Panel1
            {
                get { return panel1; }
            }
    
        }
    

    //User control one
    
    public UserControl1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
      Form1 form = Application.OpenForms.OfType<Form1>().FirstOrDefault();
                form.Panel1.Controls.Clear();
                UserControl2 m = new UserControl2();
                form.Panel1.Controls.Add(m);
               
            }
    
    Doesn't this answer your question?
    • Marked as answer by jonesjohn Wednesday, August 06, 2014 9:02 AM
    Wednesday, August 06, 2014 8:30 AM

All replies

  • In the Form where the Panel is defined, you could add a property that exposes it:

        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            public Panel Panel1
            {
                get { return panel1; }
            }
    }
    

    You can then access this property from any other class by first getting a reference to the Form and then access its properties as usual:

                Form1 form1 = Application.OpenForms.OfType<Form1>().FirstOrDefault();
                form1.Panel1.Controls.Add(...);
    

    Monday, August 04, 2014 8:18 AM
  • Excactly what I was looking for.Obliged.

    As someone who has done this.

    Do you think that the approach I took is the most appropraite for the situation or Is there another better way?How do you acheive this kind of scenario in your application?

    Monday, August 04, 2014 8:35 AM
  • If you're doing everything in the one form then put your navigation or whatever you want to call it in the Window rather than the usercontrols themselves.

    You'll have a problem if you new up a usercontrol from inside another one.

    Say you're in uc1 and you want to "navigate" to uc2.

    So you new up uc2 and substitute that for the contents of your panel in the main window.

    UC2 is a private member of uc1 now.

    SO if you dispose UC1 the UC2 goes.

    So instantiating your usercontrols from within each other is a TERRIBLE plan.

    Put your navigation on the Window and then all the usercontrols are private members of the thing which will be there all the time.  No problems that way.

    If you really need to swop usercontrols from inside one of them then:

    Expose a public event or property from your window.  Use that to tell the window what to do.  Only remember that the event in the usercontrol will have to finish before it goes away.

    The way to do this without tight coupling between everything is to use messaging.  I would use the messaging out of MVVM light for this.  Although it's aimed at XAML developers the messaging is just 3 classes and will work fine in winforms.  You could install MVVM Light using Nuget but I suggest you instead go find just those 3 classes.

    I think you can just cut and paste from here:

    http://msdn.microsoft.com/en-us/magazine/dn745866.aspx

    A message is identified by it's type - that's just a class.

    Sending a message:

                    var msg = new NavigatePage { Page = dp };
                    Messenger.Default.Send<NavigatePage>(msg);

    Subscribing and acting:

                Messenger.Default.Register<NavigatePage>(this, (action) => ReceiveNavigateMessage(action));
    //
            }
    
            private object ReceiveNavigateMessage(NavigatePage navigatePage)
            {
                this.MainPanel.Content = navigatePage.Page;
                return null;
            }

    Monday, August 04, 2014 8:36 AM
  • Now I am lost.I think you are talking about  WPF hence MVVM.But if its not the case, I would love to see how that actually works.perhaps if you have a small application which demonstrates that, which I can download and study.Any materials would be appreciated.User friendly is the major thing in my application.Thanks again.
    Monday, August 04, 2014 8:55 AM
  • Hi jonesjohn

    According to my understanding, you want to create a panel that can be called in other forms or user controls.

    Here is my steps about how to expose the panel to other form:

    Step1:

    Change the access modifier of the panel and the controls in it from private to public.

    public System.Windows.Forms.Panel panel1;
    public System.Windows.Forms.ComboBox comboBox1;
    public System.Windows.Forms.Button button1;

    Step2:

    In the other form or user control, change the Constructor with adding a parameter.

    public Form2(Form1 form)
            {
                InitializeComponent();
                this.form1 = form;
            }
            Form1 form1 = new Form1();
    private void button1_Click(object sender, EventArgs e)
            {
         // Here can get the name of the panel1
                this.textBox1.Text = form1.panel1.Name;
            }
    
    public UserControl1(Form1 form)
            {
                InitializeComponent();
                this.form1 = form;
            }
            Form1 form1 = new Form1();
    
    private void button1_Click(object sender, EventArgs e)
            {
                // Here can get the name of the panel1
                this.textBox1.Text = form1.panel1.Name;
            }

    If you still have problems, please feel free to let me know.

    Best regards,

    Tony


    • Edited by _Omar Wednesday, August 06, 2014 2:40 AM
    Wednesday, August 06, 2014 2:39 AM
  • Greetings JJ.

    If you want something just like the "Properties window in visual studio", the thing to use is a control called a PropertyGrid.

    I have never had to implement a PropertyGrid myself, and I don't know if it's the best for your particular situation, but I gather that the idea is to create a class with all of the properties that you want to edit then assign it to the grid and the grid does the rest (theoretically).

    There's what looks to be some slightly out of date but still relevant info here. There are more articles to be found via a Google search.

    Wednesday, August 06, 2014 6:22 AM
  • Thanks come on tony, but it does not work.Ante, the solution you suggested wont be the best in this situation.

    This is what I did.

    //This is form1
    
     public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            //Form1 n = new Form1();
            private void button2_Click(object sender, EventArgs e)
            {
                panel1.Controls.Clear();
                UserControl1 m = new UserControl1();
                panel1.Controls.Add(m);
            }
        }
    //User control one
    
     public UserControl1()
            {
                InitializeComponent();
            }
    
            Form1 form = new Form1();
            private void button1_Click(object sender, EventArgs e)
            {
                form.panel1.Controls.Clear();
                UserControl2 m = new UserControl2(); // this does not work at all.
                form.panel1.Controls.Add(m);
               
            }


    //Form1.designer.cs
    
    public System.Windows.Forms.Panel panel1;
    public System.Windows.Forms.Button button1;

    As you might see, On form1.I have a button and a panel, "panel"1.I then clear the panel and fill it with Usercontrol1 when the button is clicked.That works.Usercontrol1 has a button.When I click the button, I would like for the panel to now display Usercontrol2.

    If you need more information please let me know.


    • Edited by jonesjohn Wednesday, August 06, 2014 7:25 AM
    Wednesday, August 06, 2014 7:24 AM
  • As I already told you (?), you need to access the Panel of the already open instance of Form1:

    public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button2_Click(object sender, EventArgs e)
            {
                panel1.Controls.Clear();
                UserControl1 m = new UserControl1();
                panel1.Controls.Add(m);
            }
    
     //added property:
     public Panel Panel1
            {
                get { return panel1; }
            }
    
        }
    

    //User control one
    
    public UserControl1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
      Form1 form = Application.OpenForms.OfType<Form1>().FirstOrDefault();
                form.Panel1.Controls.Clear();
                UserControl2 m = new UserControl2();
                form.Panel1.Controls.Add(m);
               
            }
    
    Doesn't this answer your question?
    • Marked as answer by jonesjohn Wednesday, August 06, 2014 9:02 AM
    Wednesday, August 06, 2014 8:30 AM
  • It works, much obliged.I have another problem, I thought to ask it here without creating a new thread.

    My application should allow users to add buttons i.e  this information will be read from a database.

    My idea and what I searched is that create an array of buttons according to the number of rows and add the buttons.When I try that, They are always in one place.

    Sure, someone had to develop buttons at run time from a table.Any suggestions would be appreciated.This is my first big desktop application after finishing to read the book.So bear with me.

    Wednesday, August 06, 2014 9:07 AM