Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Organising UI code in .NET forms

I'm someone who has taught myself programming, and haven't had any formal training in .NET programming.

A while back, I started C# in order to develop a GUI program to control sensors, and the project has blossomed. I was just wondering how best to organise the code, particularly UI code, in my forms.

My forms currently are a mess, or at least seem a mess to me.

  • I have a constructor which initialises all the parameters and creates events.
  • I have a giant State property, which updates the Enabled state of all my form control as users progress through the application (ie: disconnected, connected, setup, scanning) controlled by a States enum.
  • I have 3-10 private variables accessed through properties, some of which have side-effects in changing the values of form elements.
  • I have a lot of "UpdateXXX" functions to handle UI elements that depend on other UI elements - ie: if a sensor is changed, then change the baud rate drop down list. They are separated into regions
  • I have a lot of events calling these Update functions
  • I have a background worker which does all the scanning and analysis.

My problem is this seems like a mess, particularly the State property, and is getting unmaintainable. Also, my application logic code and UI code are in the same file and to some degree, intermingled which seems wrong and means I need to do a lot of scrolling to find what I need.

How do you structure your .net forms?

Thanks

like image 915
sb3700 Avatar asked Jun 16 '10 09:06

sb3700


2 Answers

There are a number of patterns that help you seperate logic in applications , which results in cleaner and more maintainable code. The MVP pattern is a good one to start with. It is based on defining 3 areas of responisbility i.e. MVP M = Model, V = View, P = Presenter. If you are familiar with using interfaces you will be fine, otherwise that would be a good place to start (review the basic OO priciples: Encapsulation,Abstraction, Polymorphism). The basic principle of the MVP is to put you application logic in the Presenter. The presnter talks to the view (your form) via an interface, and the view calls back to the presenter (i use a interface for this too) when the user interactions with it. The model is the solution's domain object hierarchy which implments buisiness logic and entity relationships.

Most UI patterns (MVP, MCV etc) are trying to do the same things, seperate you concerns. Tghe following is a simple example:

//The view interface

interface IUserDetailsView
{

      string Username{set;get;}
      string FirstName{get;set;}
      string LastName{get;set;}
      UserDetailsPresenter Presenter{get;set;}
      void DisplayMessage(string message);


}

//The view implmentation //A standard windows form which has text boxes, labels, combos etc , which

class UserDetailsView : Form, IUserDetails
{

      public string Username{set{txtUserName.text = value;}get{return txtUserName.text;}}
      public string FirstName{set{txtFirstName.text = value;}get{return txtFirstName.text;}}
      public string LastName{set{txtLastName.text = value;}get{return txtLastName.text;}}

      Public UserDetailsPresenter Presenter{get;set;}

      public void DisplayMaessage(string message)
      {
         MessageBox.Show(message);
      }

      private void saveButton_Click(object sender, EventArgs e)
      {
         Presenter.SaveUserDetails();

      }
}

//Presentation Logic

class Presenter UserDetailsPresenter {

  //Constructor
  public userDetailsPresenter(IUserDetailsView view)
  {
    //Hold a reference to the view interface and set the view's presnter
     _view = view;
     _view.Presenter = this;
  }

  private IUserDetailsView _view;

  DisplayUser(string userName)
  {
     //Get the user from some service ...
     UserDetails details = service.GetUser(userName);

     //Display the data vioa the interface
     _view.UserName = details.UserName;
     _view.FirstName = details.FirstName;
     _view.LastName = details.LastName;

  }

  public void SaveUserDetails()
  {

       //Get the user dryaiols from the view (i.e. the screen
       UserDetails details = new UserDetails();

       details.UserName = _view.UserName;
       details.FirstName = _view.FirstName;
       details.LastName = _view.LastName;

       //Apply some business logic here (via the model)
       if(!details.IsValidUserDetails())
       {
          _view.DisplayMessage("Some detail outlining the issues");
         return;
       }

       //Call out to some service to save the data
       service.UpdateUser(details);

  }

}

//Finally, the model

public class UserDetails
{

   public UserName {get;set;}
   public FirstName{get;set;}
   public LastName{get;set;}

   public bool IsValidUserDetails()
   {
       if(LastName == "Smith")
       {
          //We do not allow smiths, remember what happened last time ... or whatever
          return false;
       }

       return true;
   }

}

Hopefully this explains how responsibility is seperated. The form has no logic apart from display/formatting etc, it can also be stubbed out for testing . The presenter is the mediator between the view and the model and makes calls to services, the model implments your business logic. As already suggested there are variations on this pattern, which can make your code a bit slimmer and more flexible but this outlines the basic principles. I hope this helps.

:-)

like image 199
NoelAdy Avatar answered Oct 02 '22 19:10

NoelAdy


With complex forms, I usually split the code into separate files. You can do this using "partial class". Each source code file is named based on the form. For example, MainForm.cs, MainForm.State.cs, MainForm.Update.cs, MainForm.Menu.cs and so on. If I have many complex forms, I will create a subfolder for each. The one tip here, is to create a MainForm.Wip.cs form. This partial class form is the code you are currently working on. Once you are done with this code, you can either rename it or move the code to other source code files.

In addition, I will also create user-controls. This has the benefit of code reuse and it moves a lot of the functionality out of the form. Check out "Developing Custom Windows Forms Controls with the .NET Framework" at http://msdn.microsoft.com/en-us/library/6hws6h2t.aspx.

Check out Nobody Cares What Your Code Looks Like at http://www.codinghorror.com/blog/2007/12/nobody-cares-what-your-code-looks-like.html. Something to think about before "organizing".

like image 41
AMissico Avatar answered Oct 02 '22 17:10

AMissico