views:

1471

answers:

3

I'm trying to modify a C# WinForms application that uses multiple forms. At startup, a login window will be shown. If the user logs in with a correct user name and password combo a form with three different tabs will be shown as a sort of administrators view. If no password or user name is supplied, a much simplified GUI will be shown. It will basically consist of two buttons that in turn shows these two forms depending on which button is pressed:

Button 1: Give the user access to a form consisting of a number of textboxes where the user can input information that will be saved to a database. Once the DB-operation has been executed successfully, the first form with the two buttons will be displayed again.

Button 2: A form is shown where the user can input a code that will be written to DB. Once the DB operation is concluded, the user will automatically be taken back to the original form with the two buttons.

Both forms will also have a back button to take the user back to the first form. I have a lot of logic in place, but I am unsure of how to best handle all the forms involved. Where should I instantiate the first (login) form? Once the login validation is done there are two possible ways to go. Either show the tabbed admin form (if user name and password is correct) or the simplified user form with two large buttons. It should also be possible to logout from the admin form so that the simplified GUI is shown instead.

I hope I am making sense here. I just need a good way to handle all the forms and navigation between them. Currently, there aren't really any need for transporting data between them, but it might be an issue in the future so a solution that takes this into account would be excellent.

I'm thinking that what is needed is really a class that handles the displaying and disposing of the forms right from the start, but I'm not quite sure where I should put the instantiation of this handling class.

+3  A: 

Form management can be a tricky issue. There are some different ways to go:

  • Just have the forms float around on the screen. Let some static class hold references to the different forms and expose methods to activate them.
  • Implement the forms as UserControls instead, put them onto the same form, and show and hide the controls as appropriate (this can also be achieved by loading the forms, stripping form borders and such and setting their parent to a panel or something similar; this will almost make them behave like user controls, but only almost)
  • There are many other methods, of course ;o)

When it comes to managing the login form, I would do that in the Main method; show the login form, check the credentials and then instantiate the UI you want to show and pass that to the Application.Run method.

Fredrik Mörk
It can indeed be a bit tricky. :) Some good suggestions I hadn't thought of, thanks. The first point seems like a quite reasonable solution since I want to be able to keep the forms I already have as intact as possible and not have to re-write too much of the code in those forms.
daft
+3  A: 

I just did something similar. I had a set of forms to manage as "pages" as the spec called them. I also had strict page flow that was a bit more complicated than yours. I'll talk you through that.

I designed each "page" of interaction as a UserControl and created an "OuterForm" and a "Controller". The controller had a Navigate(string pageName) method and the outer form contained a panel and had a Display(Control page) method which cleared the children on a panel and added the replacement.

I used Spring.NET to configure the controller and the form and used setter injection to create a two way link between the two. That meant my main method could ask Spring for the form and just display it using Application.Run(form);

I created a convenience method to access the controller from event handlers and would do e.g. Controller.Instance.Navigate(chosenPage); The controller also used Spring.NET to load the correct UserControl for chosenPage and then called on the main form to Display() the instance it loaded. There as no Spring.NET code in any user control, and no new keywords either ;-)

The advantage for me in using Spring.NET is that I had one form class that just monitored some business logic and displayed a progress indication. I was able to implement that once and configure many instances of that form injected with different business logic that it would monitor. Also, I needed to stub out interfaces to domain specific pieces of hardware and web services. Eventually I moved page flow into the configuration as well.

Simon Gibbs
Sounds like a very clean and good solution. I'll keep it ind and see what I can come up with. Thanks!
daft
+1  A: 

Have you considered using a Composite UI framework? In your case, you could use WinForms with CAB.

One of the big advantages is the support for role based authentication. An authenticated session could match one role, a non-authenticated session could match another role. Thus you can display different screens depending on the role of the user.

Another advantage is the answer to the problem of who is responsible for instantiating screens. This is managed by the controller, and actions on the screens (eg button click) can send events to this controller.

Last but not least, there are some good samples available and there is definately support for more advanced scenarios.

Dries Van Hansewijck
Thanks for the tip. I'll look into CAB as soon as I can. :-)
daft