Do you agree with them all? Are we missing some? Email me your tips, thoughts or arguments. Let me know what you think.

1. Do you design a mockup UI first?
2. Do you use code generators?
3. Do you use red and yellow colors to distinguish elements in the designer?
4. Do your applications support XP themes?
5. Do you use inherited forms for consistent behaviour?
6. Do you encapsulate (aka lock) values of forms?
7. Do you know when to use User Controls?
8. Do you know how to design a user friendly search system?
9. Do you use Validator controls?
10. Do you use DataSets or create your own business objects?
11. Do you use the designer for all visual elements?
12. Do you always use the Visual Studio designer for data binding where possible?
13. Do you avoid using MDI forms?
14. Do you have a correctly structured common code assembly?
15. Do you include Exception Logging and Handling?
16. Do you make a strongly-typed wrapper for App.config?
17. Do you replace the standard .NET DataGrid?
18. Do you avoid 3rd party menus & toolbars?
19. Do your Windows Forms applications support URLs?
20. Do you include back & undo buttons on every form?
21. Do you use NUnit to write Unit Tests?
22. Are you Data Access Layers compatible with Web Services?
23. Do you use XP button for opening a web page taking action?
  1. Do you design a mockup UI first?

    I've seen so much time wasted on complex documentation. I'm all for detailed analysis of specific business logic, but most user requirements can be encapsulated in screen mock-ups of the application. Nutting down the detail in screen mock-ups with the client brings more ideas that produces a better end product. See Do you make dummy screens before you code?

    The database schema should be designed before the mockup UI is started. Code Generation should also be done at this stage.

  2. Do you use code generators?

    Code generators can be used to generate whole Windows and Web interfaces, as well as data access layers and frameworks for business layers, making them an excellent time saver. At the simplest level, this can mean using the Data Form Wizard in Visual Studio .NET. Other code generators include:

    CodeSmith and
    RAD Software NextGeneration

  3. Do you use red and yellow colors to distinguish elements in the designer?

    Use colors on incomplete is so useful in design time:

    • Red = Controls which are incomplete, e.g. An incomplete button
    • Yellow = Controls which are deliberately invisible that are used by developers e.g. Test buttons

    Usually these controls are always yellow. However sometimes new areas on forms are made red and visible, so you can get UI feedback on your prototypes. Since they are red, the testers know not to report this unfinished work as a bug.


    Figure: Invisible controls highlighted in yellow, and incomplete items highlighted in red

  4. Do your applications support XP themes?

    All applications should be compatible with the Windows XP user interface and should be fully themed. Applications that do not use XP themes look like they were designed only for an earlier version of Windows. Mixing themed and non-themed controls looks equally unprofessional. In .NET 1.0, applying themes was difficult because you had to create a manifest file and copy it to the run directory. This is no longer the case.
    There are two steps are all you need to do:

    1. Call Application.EnableVisualStyles() at the top of the Main method of the application.
    2. Set the FlatStyle property of each control to System.


    Figure: Bad - XP themes are not used


    Figure: Good - XP themes are used

  5. Do you use inherited forms for consistent behaviour?

    If you ask a new .NET developer (from the Access or VB6 world) what is the best thing about .NET Windows Forms, most of your answers will be "Form Inheritance" that allows them to keep a nice consistent look for all forms. If you ask them a couple of months later, they will probably tell you the worst thing about .NET Windows Forms is "Form Inheritance". This is because they have had too many problems with the bugs in the form designer regarding this feature. Many abandon them altogether and jump on the user control band wagon. Please don't I have a solution to this....

    I think if you can keep the level of form inheritance to a minimum, then you may not see the problem or at least you will experience the problem less. Anyway even if you do, stop whinging and just close down Visual Studio.NET and restart. You don't change the base form that often anyway.

    Well how do you keep it to a minimum? Well make the first base form without any controls, only code (to make it as flexible as possible and avoid having a multitude of base forms).

    We try to keep the number of controls on inherited forms, and the levels of inheritance to a minimum, because it reduces the risk of problems with the Visual Studio Designer (you know when the controls start jumping around, or disappearing from the Designer, or properties getting reset on inherited copies or eventhe tab order getting corrupted). Designer errors can also occur in the task list if the InitializeComponent method fails.

    Every form in your application should inherit from a base form which has code common to every form, for example:

    • Company Icon
    • Remembering its size and location - Code sample to come in the SSW .NET Toolkit
    • Adding itself to a global forms collection if SDI (to find forms that are already open, or to close all open forms)
    • Logging usage frequency and performance of forms (load time)


    Figure: Base Form for all SSW applications with SSW icon

    a) Sorting out the StartPosition:

    1. CentreParent only for modal dialogs (to prevent multi-monitor confusion)
    2. CentreScreen only for the main form (MainForm), or a splash screen
    3. WindowsDefaultLocation for everything else (99% of forms) - prevents windows from appearing on top of one another

    b) Sorting out FormBorderStyle:

    1. FixedDialog only for modal dialog boxes
    2. FixedSingle only for the the main form (MainForm) - FixedSingle has an icon whereas FixedDialog doesn't
    3. None for splash screen
    4. Sizable for everything else (99% of forms) - almost all forms in an app should be resizable

    We have a program called SSW Code Auditor. Rules to come:

    • CentreParent must be used with FixedDialog
    • FixedDialog must be used with CentreParent
    • Only one or two forms with CentreScreen
    • CentreScreen must be used with FixedSingle
    • FixedSingle must be used with CentreScreen
    • Only one Form with FormBorderStyle = None

    c) Sorting out a base data entry form:

    1. Inherited from the original base form
    2. OK, Apply and Cancel buttons
    3. Menu control
    4. Toolbar with New, Search and Delete


    Figure: Base data entry form with menu, toolbar and OK, Cancel & Apply buttons

    Note: The data entry base form has no heading - we simply use the Title Bar

  6. Do you encapsulate (aka lock) values of forms?

    One useful feature of inherited forms is the ability to lock the value of certain properties on the inherited copy, e.g.:

    • Font - we want to maintain a consistent font across all forms
    • BackColor - changing the background color prevents the form from being themed
    • Icon - we want all of our forms to have the company Icon

    This can be achieved with the following code, which works by hiding the existing property from the designer using the Browsable attribute. The Browsable attribute set to False means "don't show in the the designer". There is also an attribute called EditorBrowsable, which hides the property from intellisense.

    C#:

    using System.ComponentModel;
    [Browsable(false)] // Browsable = show property in the Designer
    public new Font Font
    {
    get
    {
    return base.Font;
    }
    set
    {
    //base.Font = value; //normal property syntax
    base.Font = new Font("Tahoma", 8.25);
    // Must be hard coded - cannot use Me.
    }
    }

    VB.NET:

    Imports System.ComponentModel
    <Browsable(False)> _
    Public Shadows Property Font() As Font
    Get
    Return MyBase.Font
    End Get
    Set(ByVal Value As Font)
    'MyBase.Font = Value 'normal property syntax
    MyBase.Font = Me.Font
    End Set
    End Property


    Figure: Font Property Visible


    Figure: Font Property Hidden

  7. Do you know when to use User Controls?

    User controls allow you to have groups of elements which can be placed on forms.


    Figure: Good - the Address User Control is repeated

    Pros:

    • You can use a user control more than once on the same form eg. Mailing Address, Billing Address
    • You can reuse logic in the code behind the controls e.g. Search control
    • User controls are less prone to visual inheritance errors
    • When used in a form with multiple tab pages - and each tab page potentially having a lot of controls, it is possible to put each tabpage into a seperate usercontrol
    • Reduce lines of generated code in the designer by splitting it into multiple files
    • Allow multiple persons to work on different complex tabpages

    Cons:

    • You lose the AcceptButton and CancelButton properties from the Designer eg. OK, Cancel, Apply. Therefore the OK, Cancel and Apply buttons cannot be on User Controls.

    However, User Controls should not be used for every form in the application. They should only be used for elements which are shared between several forms, such as search and address controls.


    Figure: Bad use of user controls - all the forms in the application are user controls


    Figure: Bad use of user controls - all of the controls on this form are on a user control, but are only used once


    Figure: Good - user controls are only used for shared controls

  8. Do you know how to design a user friendly search system?

    A search system should be separate from the data entry fields (on a different form), to avoid confusion, should have variable criteria, and should have advanced options which allow the user to search any field at all.


    Figure: Bad Search System (Controls are on the same form as the data entry controls)


    Figure: Good Search System  (see the SSW .NET Toolkit)

  9. Do you use Validator controls?

    Validation is extremely important on a data entry form. There are two ways to do validation:

    1. ErrorProvider control
      The ErrorProvider control is code intensive. You must manually handle the Validating event of each control you want to validate, in addition to manually running the validation methods when the OK or Apply button is clicked.

      Private Sub productNameTextBox_Validating(ByVal sender As Object, _
      ByVal e As System.ComponentModel.CancelEventArgs) Handles _
      productNameTextBox.Validating
      ValidateProductName(False)
      End Sub
      Private Function ValidateProductName(ByVal force As Boolean) _
      As Boolean
      If Me.productNameTextBox.Text.Length = 0 Then
      Me.errorProvider.SetError(Me.productNameTextBox,
      "You must enter the Product Name.")
      If force Then
      MessageBox.Show("You must enter the Product Name.", _
      Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Warning)
      End If
      Return False
      Else
      Me.errorProvider.SetError(Me.productNameTextBox, _
      String.Empty)
      Return True
      End If
      End Function
      Private Function ValidateInput() As Boolean
      Dim force As Boolean = True
      Dim isValid As Boolean = ValidateProductID(force)
      If Not isValid Then
      force = False
      End If
      isValid = ValidateProductName(force)
      If Not isValid Then
      force = False
      End If
      isValid = ValidateCategory(force)
      Return isValid
      End Function
      Private Sub okButton_Click(ByVal sender As Object, _
      ByVal e As System.EventArgs)
      If Me.ValidateInput() Then
      'Test
      End If
      End Sub

      Bad, lots of code but no balloon tooltips

      Private Sub productNameTextBox_Validating(ByVal sender As Object, _
      ByVal e As System.ComponentModel.CancelEventArgs) _
      Handles productNameTextBox.Validating
      ValidateProductName(False)
      End Sub
      Private Function ValidateProductName(ByVal force As Boolean) _
      As Boolean
      If Me.productNameTextBox.Text.Length = 0 Then
      Me.errorProvider.SetError(Me.productNameTextBox, _
      "You must enter the Product Name.")
      If force Then
      If Me.balloonToolTip.IsSupported Then
      Me.balloonToolTip.SetToolTip(Me.productNameTextBox, _
      "You must enter the Product Name.")
      Else
      MessageBox.Show("You must enter the Product Name.", _
      Me.Text, MessageBoxButtons.OK,
      MessageBoxIcon.Warning)
      End If
      End If
      Return False
      Else
      Me.errorProvider.SetError(Me.productNameTextBox, _
      String.Empty)
      Return True
      End If
      End Function
      Private Function ValidateInput() As Boolean
      Dim force As Boolean = True
      Dim isValid As Boolean = ValidateProductID(force)
      If Not isValid Then
      force = False
      End If
      isValid = ValidateProductName(force)
      If Not isValid Then
      force = False
      End If
      isValid = ValidateCategory(force)
      Return isValid
      End Function
      Private Sub okButton_Click(ByVal sender As Object, _
      ByVal e As System.EventArgs)
      If Me.ValidateInput() Then
      'Test
      End If
      End Sub

      Good, lots of code but balloon tooltips are used

      Note: The component for balloon tooltips can be found in the SSW .NET Toolkit.

      The error provider has the advantage over the extended provider that it can be used with balloon tooltips. If you are not using balloon tooltips, however, the error provider should not be used.


      Figure: .NET ErrorProvider Control with a custom balloon tooltip

    2. SSW Extended Provider
      The SSW Extended Provider integrates with the ErrorProvider control to provide the same functionality, but requires no code to implement (everything can be done in the Designer).


      Figure: SSW Extended Provider controls and properties on a TextBox
       

  10. Do you use DataSets or create your own business objects?

    In .NET, there are two ways to pass data through the layers of your application. You can:

    • Use DataSet objects, OR
    • Write your own custom business objects

    There are two very different opinions on this matter amongst .NET developers...

    The PROs of the DataSet object:

    • Code Generation
      Strongly typed DataSet objects can be created automatically in Visual Studio. Custom business objects must be laboriously coded by hand.
    • CRUD functionality
      DataSet
      objects automatically provide CRUD (create, read, update, delete) support. You must manually implement this functionality with custom business objects.
    • Concurrency
      Support for concurrency is part of the DataSet object. Again, you must implement this yourself in a custom business object.
    • Data binding
      It is difficult and time-consuming to write custom business objects that are compatible with data binding. The DataSet object is designed for data binding.

    The PROs of Custom Business Objects:

    • Better performance
      The DataSet object is a very heavy object and is memory-intensive. In contrast custom business objects are always much more efficient. Business objects are usually faster when manipulating data, or when custom sorting is required.
    • Business objects allow you to combine data storage (NOT data access) and business logic (e.g. validation) in the one class. If you use DataSet objects, these must be in separate classes.

    Microsoft's official word on this matter is explained in Designing Data Tier Components and Passing Data Through Tiers.

  11. Do you use the designer for all visual elements?

    The designer should be used for all GUI design. Controls should be dragged and dropped onto the form and all properties should be set in the designer, e.g.

    • Labels, TextBoxes and other visual elements
    • ErrorProviders
    • DataSets (to allow data binding in the designer)

    Things that do not belong in the designer:

    • Connections
    • Commands
    • DataAdapters

    However, and DataAdapter objects should not be dragged onto forms, as they belong in the business tier. Strongly typed DataSet objects should be in the designer as they are simply passed to the business layer. Avoid writing code for properties that can be set in the designer.


    Figure: Bad - Connection and Command objects in the Designer


    Figure: Good - only visual elements in the designer

  12. Do you always use the Visual Studio designer for data binding where possible?

    Basic data binding should always be done in the designer because the syntax for data binding is complex, and confusing for other developers reading the code.

    Figure: Simple data binding (binding to a single property) in the designer

    Figure: Complex data binding (binding to a list) in the designer

    When you need to handle the Format or binding events, you can still use designer data binding, as long as you hook in your events prior to filling data.

    private void Form1_Load(object sender, System.EventArgs e)
    {
    Binding currencyBinding = this.textBox1.DataBindings("Text");
    currencyBinding.Format += new
    ConvertEventHandler(currencyBinding_Format);
    currencyBinding.Parse +=
    new ConvertEventHandler(currencyBinding_Parse);
    OrderDetailsService.Instance.GetAll(Me.OrderDetailsDataSet1);
    }
    private void currencyBinding_Format(object sender, ConvertEventArgs e)
    {
    if(e.DesiredType == typeof(string))
    {
    e.Value = ((decimal)e.Value).ToString("c");
    }
    }
    private void currencyBinding_Parse(object sender, ConvertEventArgs e)
    {
    if(e.DesiredType == typeof(decimal))
    {
    e.Value = Decimal.Parse(e.Value.ToString(),
    System.Globalization.NumberStyles.Currency);
    }
    }
  13. Do you avoid using MDI forms?

    MDI forms should be avoided in most modern data-centric applications because they:

    • Are a hangover from the days of Windows 3.1 and Access 2.0
    • Constrained within a smaller window
    • Only show as one window on the taskbar
    • Have no multiple monitor support (the killer reason)

    What about tabs, as used in VS .NET, and browsers such as Mozilla and CrazyBrowser? They are good for developers, but not users. Users are used to Outlook, which does not use MDIs at all. If the users want to group windows, Windows XP lets you "Group Similar Taskbar Icons".


    Figure: Bad Example (Word 2003 in MDI mode)


    Figure: Good Example (Word 2003 with Default Settings)

    Me.IsMdiContainer = true;
    ClientForm frm = new ClientForm();
    frm.MdiParent = this;
    frm.Show();

    Bad code example using MDI forms

    ClientForm frm = new ClientForm();
    frm.Show();

    Good code example - not using MDI

    MDI forms have the advantage that the MDI parent form will have a collection MdiChildren which contains all of its child forms. This makes it very easy to find out which forms are already open, and to give these forms focus. Accomplishing this with an SDI application requires you to:

    • A global collection of forms
    • A line of code on the load and closed events of each form which adds / removes the form from the global collection
  14. Do you have a correctly structured common code assembly?

    Your common code assembly should be divided into the following sections:

    • Common (e.g. SSW.Framework.Common)

      • Code which is not UI specific
      • Example: Code to convert a date into different formats
    • CommonWindows (e.g. SSW.Framework.WindowsUI)
      • Example: Base forms which are the same for all products, wizard frameworks
    • CommonWeb (e.g. SSW.Framework.WebUI)
      • Example: Generic XML-based navigation components

    For more information see Do you have a consistent .NET Solution Structure?.

  15. Do you include Exception Logging and Handling?

    All unhandled exceptions should be logged to provide developers with sufficient information to fix bugs when they occur. There are two options we for logging exceptions:

    1. The Microsoft Exception Management Application Block
      Microsoft provides full source code for the EMAB, which is fully extensible with custom logging target extensions. We decided to customize the EMAB to produce the SSW Exception Management Block, which logs exceptions to a database using a web service, allowing us to keep a history of all exceptions.


      Figure: Exception Reporting Web Service
       

    2. Log4Net is an open-source logging library for .NET base on the Log4J library. It is extremely capable, and will suit the logging needs of my current project, but I can't imagine a case where I wouldn't be able to find a place for this tool in future projects.

      One of the standout attribute of this library is its documentation. Its use of XML code comments, and extensive reference documentation is a credit to the authors, and has set the standard of how we would like our developers to achieve in our code.

      Log4Net allows you to pepper you code with log writing methods of different severities. You can then define in a separate XML .config file how reports on each severity error should be sent (in fact, even inside these severities you can decide how particular entries are reported). In our case "Info" log writes are sent to the Debug and Trace windows, Anything above "Error" is written to a SQL Server database, and "Critical" Errors are also emailed, and written to the Event Log. Because all of these settings are in a .config file, we can change it at runtime whilst the application is running on our production server (it has a file watcher to know when this config file has been edited).

    Your code should not contain any empty catch blocks as this can hamper exception handling and debugging.

    We have a program called SSW Code Auditor to check for this rule. The regular expressions use to check this are:

    • For C#:

      • To find a Main method without EMAB:
        void/s+Main/([^)]*/)/s*{(?!/s*Application/.TreadException/s+/+=/s+new/s+(System/.Threading/.)?ThreadExceptionHandler/((Microsoft/.ApplicationBlocks/.ExceptionManagement/.)?ExceptionManager/.ThreadExceptionHandler/);).*/s+}
      • To find empty catch blocks:
        catch/s*(?:/(/s*Exception/s+[A-Za-z][A-Za-z0-9-]*/s*/))?/s*{/s*}
    • For VB:
      • To find a main method without EMAB:
        (<Reference/s+(Name/s+=/s+"SSW/.Framework/.ExceptionManagement")/s+(AssemblyName/s+=/s+"SSW/.Framework/.ExceptionManagement")/s+(HintPath/s+=/s+"[^"]*SSW/.Framework/.ExceptionManagement/.dll")/s+/>)
      • To find empty catch blocks:
        Catch/s+(?:/w+?/s+?As/s+?[a-z]*Exception)?/s*End Try
  16. Do you make a strongly-typed wrapper for app.config?

    If your application accesses properties in app.config, you should provide a strongly typed wrapper for the app.config file. The following code shows you how to build a simple wrapper for app.config in an AssemblyConfiguration class:

    using System;
    using System.Configuration;
    namespace SSW.Northwind.WindowsUI
    {
    public sealed class AssemblyConfiguration
    {
    // Prevent the class from being constructed
    private AssemblyConfiguration() { }
    public static string ConnectionString
    {
    get
    {
    return
    ConfigurationSettings.AppSettings["ConnectionString"].
    ToString();
    }
    }
    }
    }

    Unfortunately, the Configuration Block does not automatically provide this wrapper.

  17. Do you replace the standard .NET DataGrid?

    The standard DataGrid in Visual Studio 2003 has some limitations. It is ugly compared to a ListView and does not support combo box or button columns, making it useless for many applications. (This is going to be fixed in Visual Studio 2005 with the new DataGridView control). However, Infragistics provide an XP-themed DataGrid which provides similar functionality to VS 2005's DataGridView.


    Figure: Infragistics UltraGrid


    Figure: Visual Studio 2005 DataGridView

  18. Do you avoid 3rd party menus & toolbars?

    The menu & toolbar controls in Visual Studio .NET 2003 do not allow you to have icons in your menus or have alpha-blended toolbar icons. They also do not provide an Office-2003 like look. However, we have tried several third party menu and toolbar controls and all of them had serious bugs, e.g.

    Instead of using the 3rd party controls, we are going to use the standard menu and toolbar until Visual Studio 2005 which provides Office 2003 style menus and toolbars with the new ToolStrip control, which it will be easy to upgrade to. Upgrading from these 3rd party controls will be difficult.


    Figure: Visual Studio 2005 Office 2003-like controls (ToolStrip designer)

    However, it would be better if VS 2005 stored the details of menus and toolbars in an XML file.

  19. Do your Windows Forms applications support URLs?

    What is the one thing a web browsers has over a Windows Forms application - a URL! With a Windows Forms application, you typically have to wade through layers of menus and options to find a particular record or "page". However, Outlook has a unique feature which allows you to jump to a folder or item directly from the command line.


    Figure: Outlook can automatically jump to a specified folder or item from a command line


    Figure: Outlook address bar (Web toolbar) shows you the URL for every folder

    We believe that all applications should have this capability. You can add it to a Windows Application using the following procedure:

    1. Add the necessary registry keys for the application

      • HKEY_CLASSES_ROOT/AppName/URL Protocol = ""
      • HKEY_CLASSES_ROOT/AppName/Default Value = "URL:Outlook Folders"
      • HKEY_CLASSES_ROOT/AppName/shell/Default Value = "open"
      • HKEY_CLASSES_ROOT/AppName/shell/open/command/Default Value = "Path/AssemblyName.exe /select %1"
    2. Add code into your main method to handle the extra parameters.

      C#:
       

      public static void Main(string[] args)
      {
      ...
      if(args.Length > 0)
      {
      string commandData = args[1].Substring(args[1].IndexOf(":") +
      1).Replace("/"", String.Empty);
      Form requestedForm = null;
      switch(commandData)
      {
      case "Client":
      {
      requestedForm = new ClientForm();
      break;
      }
      // Handle other values
      default: // Command line parameter is invalid
      {
      MessageBox.Show("The command line parameter specified" +
      " was invalid.", "SSW Demo App",
      MessageBoxButtons.OK, MessageBoxIcon.Error);
      // Exit the application
      return;
      }
      }
      requestedForm.Show();
      // Show the main form as well
      MainForm mainForm = new MainForm();
      mainForm.Show();
      // Give the requested form focus
      requestedForm.Focus();
      Application.Run(mainForm);
      }
      else // No command line parameters
      {
      // Just show the main form
      Application.Run(new MainForm());
      }
      }

      VB .NET:

      Public Shared Sub Main()
      ...
         Dim args As String = Microsoft.VisualBasic.Command()
      If args.Length > 0
      Dim commandData As String = _
      args.Substring(args.IndexOf(":") + 1).Replace("""", "")
      Dim requestedForm As Form = Nothing
      Select Case commandData
      Case "Client"`
      requestedForm = New ClientForm()
      ' Handle other values
      Case Else ' Command line parameter is invalid
      MessageBox.Show("The command line parameter specified " &_
      "was invalid.", "SSW Demo App", MessageBoxButtons.OK, &_
      MessageBoxIcon.Error);
      ' Exit the application
      Exit Sub
      End Select
      requestedForm.Show()
      ' Show the main form as well
      Dim mainForm As MainForm = New MainForm()
      mainForm.Show()
      ' Give the requested form focus
      requestedForm.Focus()
      Application.Run(mainForm);
      Else ' No command line parameters, just show the main form
      Application.Run(new MainForm())
      End If
      End Sub
  20. Do you include back & undo buttons on every form?

    Following on from including a URL, every form should have a back and an undo button which takes you back to the previous screen, or reverses you last action respectively. This is just like Outlook has a back button to take you to the previous folder on the Web toolbar (see above).

    The list of forms/URLs and the order in which they have been accessed should be stored in a DataSet held in memory (like IE) - not saved to disk. For example:

    Menu Action Undo Back Cut Remember: Remember Text and Cursor Position Cut To Clipboard Return to Remember n/a Save Record Remember old values Execute procCustomerSave Close Form Return to Old values Reopen form

    Menu Action Undo Back
    Cut Remember: Remember Text and Cursor Position
    Cut To Clipboard
    Return to Remember n/a
    Save Record Remember old values
    Execute procCustomerSave
    Close Form
    Return to Old values Reopen form

    Sample code to come in the SSW .NET Toolkit.

  21. Do you use NUnit to write Unit Tests?

    Unit tests are a valuable tool when maintaining code, particularly in a team environment where you may have to fix a bug in someone else's code. Unit Tests ensure that you do not introduce new bugs in someone else's code, or code that you have not looked at for a while. We like NUnit because it is free, we have found that it is easy for developers to learn and it integrates well with Visual Studio. Visual Studio .NET 2005 integrates Unit Testing with Visual Studio Team System. We will use this when Visual Studio 2005 is released.

    Unit tests should also be accessible from the Help menu to assist in troubleshooting when your users call up tech support. For more information see Rules to Better Interfaces.

    Note: Unit testing also works with Web projects.

  22. Are you Data Access Layers compatible with Web Services?

    Data Access Layers should support not only direct connections to SQL Server (best performance when running locally) but also connections through web services (best performance when running remotely). There are three ways to implement this:

    1. Lots of if statements (really messy - most people try this first)
    2. Interfaces (Implements statement in VB)
    3. Factory pattern (best - most flexible and extensible approach)
  23. Do you use XP button for opening a web page taking action?

    If it's simply opening a web page containing just more information or help then use hyperlink.

    Figure: Simple hyperlink

    But when it requires some form of action (e.g. generating reports, passing and processing values), use XP button with an image.

    Figure: XP button with image (good)
     
     
    Figure: Hyperlink (bad) Figure: Hyperlink on a button (bad) Figure: Normal button (bad)

Rules to Better Windows Forms Applications相关推荐

  1. 开源自己用python封装的一个Windows GUI(UI Automation)自动化工具,支持MFC,Windows Forms,WPF,Metro,Qt...

    首先,大家可以看下这个链接 Windows GUI自动化测试技术的比较和展望 . 这篇文章介绍了Windows中GUI自动化的三种技术:Windows API, MSAA - Microsoft Ac ...

  2. Exposing Windows Forms Controls as ActiveX controls

    转:http://www.codeproject.com/cs/miscctrl/exposingdotnetcontrols.asp?df=100&forumid=2373&exp= ...

  3. (C#)安全、简单的Windows Forms多线程编程 (一)

    (C#)安全.简单的Windows Forms多线程编程  (一) Chris Sells June 28, 2002 翻译:袁晓辉 www.farproc.com farproc#AT#gmail# ...

  4. Spread for Windows Forms高级主题(3)---单元格的编辑模式

    理解单元格的编辑模式 通常情况下,当终端用户双击单元格时,编辑控件将允许用户在该单元格中输入内容.在一个单元格中编辑的能力被称为编辑模式.一些属性和方法可以用来自定义编辑模式的使用. 当一个单元格处于 ...

  5. System.Windows.Forms.Timer在线程中的注意事项

    在WinForm中使用System.Windows.Forms.Timer对象,如果是在单线程中使用,则直接设置该对象的Enabled属性值即可启动计时器,但如果是在多线程窗体中在多线程引发的事件中调 ...

  6. Spread for Windows Forms高级主题(5)---数据处理

    2019独角兽企业重金招聘Python工程师标准>>> 使用表单的API处理数据 你可以将数据以有格式或无格式字符串或者数据对象的形式填充到单元格中.将数据填充到单元格的最好方式取决 ...

  7. Create C++ Windows Forms Application in Visual Studio 2017

    Background: From Windows Forms Application in Visual C++ ???!!!!: "MS removed the WinForms C++/ ...

  8. Spread for Windows Forms高级主题(7)---自定义打印的外观

    2019独角兽企业重金招聘Python工程师标准>>> 表单打印的多个部分都可以进行自定义,大多数的自定义选项存在于PrintInfo对象中.大多数打印选项是在PrintInfo对象 ...

  9. System.Windows.Forms.ListView : Control

    #region 程序集 System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ...

最新文章

  1. 让Linux系统开机速度更快的方法
  2. java char 默认值_java 中char 的初始值
  3. h5py快速入门指南
  4. 项目分析(map复习)
  5. 在线交友背后的数学原理
  6. aggregation java_Elasticsearch Aggregation 多个字段分组统计 Java API实现
  7. python科学计算三剑客_1-python数据分析-数据分析介绍、数据分析三剑客之NumPy
  8. OpenCV4每日一练day6:Image Watch的使用
  9. 在 MT4 指标中设置邮件提醒
  10. QuickCHM 2.6中“不支持此接口”错误的“彻底”解决(补丁)
  11. 计算机科学与技术导论结课报告,计算机科学与技术导论论文提纲范文模板 计算机科学与技术导论论文框架怎样写...
  12. t32 emulation debug port failed
  13. 量化思维与常见的量化标
  14. 你负责健康快乐长大,我负责学做一个合格的妈妈
  15. 百度网盘PC端缓存文件夹
  16. Failed to evaluate mask initialization commands
  17. Radon定理与证明
  18. HTTP之原理,长短连接,响应码,三握四挥,八种方法
  19. java循环遍历队列_java实现循环队列
  20. 高校借助电子签章推动学生入网缴费凭证、科研项目拨款单在线签

热门文章

  1. Beta阶段项目展示
  2. 使用十六进制表示颜色
  3. 修改掉Linux内核缺页中断处理的exception fixup表
  4. python抠图_Python用5行代码实现批量抠图的示例代码
  5. php应用开发读书笔记,读《高性能 PHP 应用开发》笔记
  6. 应届生数据分析求职记
  7. 有状态服务和无状态服务的区别
  8. 第1章:开始启程 - 你的第一行android代码
  9. MATLAB对轮胎图形做均衡变换
  10. 我的世界虚拟服务器架设,我的世界Minecraft服务器架设教程_服务器怎么建立