CBreeze
CBreeze

Reputation: 2965

C# Switching Between Interface in the Same Form

I've written a Database program in Java and I am now wishing to convert it into C# for learning purposes.

A problem I have come across is switching between different views in the same user interface. I would like to keep one form throughout the program and change the contents displayed on it as the user moves through the program.

I have attempted to add a panel onto the form where I add a user control that contains a button. On clicking the button the initial user control should be disposed of and a new user control displayed.

This is my code so far;

public partial class Form1 : Form
{

    UserControl1 myControl1 = new UserControl1();
    UserControl2 myControl2 = new UserControl2();

    public Form1()
    {
        InitializeComponent();
        panel1.Controls.Add(myControl1);
    }

    public void PanelVersion2()
    {
        panel1.Controls.Remove(myControl1);
        panel1.Controls.Add(myControl2);
    }
}

And in my UserControl class;

public partial class UserControl1 : UserControl
{
        public event EventHandler AddControl;
        public UserControl1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Form1 fm = new Form1();
            fm.PanelVersion2();
        }
    }
}

Is this ideology the "best" way to create a UI? Is there a more efficient way to move through the user interface whilst keeping the original form?

Upvotes: 1

Views: 2462

Answers (3)

Joachim Olsson
Joachim Olsson

Reputation: 316

As the question is about WinForms and I don't want to, well.. go against convention and answer with a suggestion for you to use a different technology right away I will answer the question normally first and provide afterthoughts under on what I suggest you actually do. Whatever anyone says, never use MDI for this. It is not intended for this and will just baffle your users. So here it goes, a small view based controller framework with a minimalistic approach.

First the host form's interface (IHost.cs):

public interface IHost
{
    /// <summary>
    ///     Destroys the current view and creates a new from name
    /// </summary>
    /// <param name="name">The name of the view you wish to start</param>
    void SwitchView(string name);

    View CurrentView { get; }
}

Then, the views interface. Now, visual studio will tell you this is a UserControl in the design. Mistake not! It is, but should not be used as one. Never actually put stuff on that designer, should you do remove the classes it creates on the right hand side. This is a base for all views, if you edit this all views will have that part of the interface. (View.cs)

    using System.Windows.Forms; //Above your namespace

    public class View : UserControl
    {
        /// <summary>
        ///     Warning! Attempting to use this constructor and host (eg switching views)
        ///     will result in exceptions unless host is manually set
        /// </summary>
        protected View()
        {
        }
        protected View(IHost host) 
        {
            Host = host;
        }

        public virtual IHost Host { get; }
    }

Now the host form looks like this (HostForm.cs, this is my entry point and the thing I show the main user):

    using System.Collections.Generic; //Above your namespace
    using System.Windows.Forms; //Above your namespace

    public partial class HostForm : Form, IHost
    {
        public View CurrentView { get; private set; }

        public HostForm()
        {
            InitializeComponent();
            SwitchView("UserLabel");
        }

        public void SwitchView(string name)
        {
            Controls.Remove(CurrentView);
            CurrentView = CreateViewFromName(name);
            Controls.Add(CurrentView);
            CurrentView.Show();
        }

        private View CreateViewFromName(string name)
        {
            switch (name.ToLowerInvariant())
            {
                case "userlabel":
                    return new UserLabel(this);
                case "usertext":
                    return new UserText(this);
            }
            throw new KeyNotFoundException("Could not find a form with that name!");
        }
    }

From here on, create a normal UserControl but in the cs code change "UserControl" to View and in your host form add a name conversion for it like you've seen above. Here are two views I created (design omitted) (UserLabel.cs)

    public partial class UserLabel : View
    {
        public UserLabel(IHost host) : base(host)
        {
            InitializeComponent();
        }

        private void SubmitButton_Click(object sender, System.EventArgs e)
        {
            Host.SwitchView("UserText");
        }
    }

(UserText.cs)

    public partial class UserText : View
    {
        public UserText(IHost host) : base(host)
        {
            InitializeComponent();
        }

        private void LoginButton_Click(object sender, EventArgs e)
        {
            Host.SwitchView("UserLabel");
        }
    }

Feel free to ask questions on this design in the comment section.

Now as for what I actually recommend? If you need windows desktop applications, and don't want to target the universal app framework I recommend WPF. Both Wikipedia and Microsoft Developer Network(MSDN) have great instructions on how to get started. As for pattern I recommend you use MVVM and move on from there. Lots of resources are available online.

Upvotes: 0

CodeCaster
CodeCaster

Reputation: 151586

You don't let forms show forms, and rather not let a form decide which panel to show, because then it's incredibly hard to properly keep track of the windows in your application from code. Yeah, you can iterate over Application.OpenForms or someContainer.Controls to find what you're looking for, but you don't want that.

You need to apply design patterns, like MVP, MVVM, MVC or application controller.

To explain those patterns in this answer would make it a bit long (I may do an attempt later), but try searching on the mentioned terms.

Upvotes: 2

Jhonny D. Cano -Leftware-
Jhonny D. Cano -Leftware-

Reputation: 18013

Maybe you should separate the responsibilities of the form from the responsibility of the user control, and maybe keeping a reference to the main form into the control could help

UserControl1 myControl1 = new UserControl1 { MainForm = this };

This is just a suggestion for a learning example, maybe you should search for a UI design pattern in order to do something more elaborated.

Upvotes: 0

Related Questions