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 button on EVER Y 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?
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. 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 andRAD Software NextGeneration Do you use red and yellow colors to distinguish elements in the designer use colors on incomplete is so useful in des? Ign Time:
Red = Controls which are incomplete, eg An incomplete button Yellow = Controls which are deliberately invisible that are used by developers eg 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 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:
Call Application.EnableVisualStyles () at the top of the Main method of the application Set the FlatStyle property of each control to System Figure:.. Bad - XP themes are not used Figure: Good - XP themes are used 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 The 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. Anyw Ay Even if you do, stop covene 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 fre Quency and Performance of Forms (Load Time) Figure: Base Form for All Ssw Applications with ssw icon a) sorting out the startposition:
CentreParent only for modal dialogs (to prevent multi-monitor confusion) CentreScreen only for the main form (MainForm), or a splash screen WindowsDefaultLocation for everything else (99% of forms) - prevents windows from appearing on top of one another b) Sorting OUT FORMBORDERSTYLE:
FixedDialog only for modal dialog boxes FixedSingle only for the the main form (MainForm) - FixedSingle has an icon whereas FixedDialog does not None for splash screen 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: Inherited from the original base form OK, Apply and Cancel buttons Menu control 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 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, EG:
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 IconThis 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 "do not 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 protection 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
Public Shadows Property font () AS FONT
Get
Return mybase.font
END GET
SET (ByVal Value As Font)
'Mybase.font = value' normal property syntaxmybase.font = me.font
End set
End Property Figure: Font Property Visible Figure: Font Property Hidden 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 eg 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 can not 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 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 Sear ch System (see the SSW .NET Toolkit) Do you use Validator controls Validation is extremely important on a data entry form There are two ways to do validation:?.. ErrorProvider controlThe ErrorProvider control is code intensive You must manually handle the Validating event of .
Private sub productnametextbox_validating (byval sender as objecting)
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.seeterror (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 Subbad, LOTS of Code But no Balloon Tooltips
Private sub productnametextbox_validating (byval sender as objecting)
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 validateInd () as booleandim 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 SubGood, 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 SSW Extended ProviderThe 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 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 TWO VERY DIFFERENT OPINIONS ON This Matter Amongst .Net Developers ... The Pros of the DataSet Object:
Code GenerationStrongly typed DataSet objects can be created automatically in Visual Studio. Custom business objects must be laboriously coded by hand. CRUD functionalityDataSet objects automatically provide CRUD (create, read, update, delete) support. You must manually implement this functionality with custom business objects . ConcurrencySupport for concurrency is part of the DataSet object. Again, you must implement this yourself in a custom business object. Data bindingIt 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 performanceThe 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 (eg 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. 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, EG
Labels, TextBoxes and Other Visual Elements ErrorProviders DataSets (To Allow Data Binding In The Designer) 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 Do you always use the Visual Studio designer for data binding where possible Basic data binding should always be done in the designer? BECAUSE 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 flpring 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_pars);
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_Pars (Object Sender, ConvertEventArgs E)
{
IF (E.DesiredType == TypeOf (Decimal))
{
E.Value = decimal.pars (E.Value.toString (),
System.globalization.numberStyles.currency;
}
} 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 .............................. ..
Me.ismdicontAiner = true;
Clientform fm = new clientform ();
Frm.mdiparent = this;
frm.show (); Bad Code Example Using MDI Forms
Clientform fm = 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 There Forms Focus. Accomplishing this with an sdi application request 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 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 In Different Formats CommonWindows (E.G. Ssw.Framework.windowsui)
Example: Base forms which are the same for all products, wizard frameworks CommonWeb (eg SSW.Framework.WebUI) Example: Generic XML-based navigation components For more information see Do you have a consistent .NET Solution Structure ?. Do you include Exception Logging and handling? All unhandled Exceptions Should Be Logged to Provide Developers with sufficient information to fix bugg desy Occur. There is:
The Microsoft Exception Management Application BlockMicrosoft 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 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 not imagine a case where I would not 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 You Code with log Writing methods of diffent severities. You Can Th en 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 area: 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: (
Using system;
Using system.configuration;
Namespace ssw.northwind.windowsui
{
Public Sealed Class AssemblyConfiguration
{
// prevent the class from being constructed
PRIVATEMBLYCONFIGURATION () {}
Public Static String Connectionstring
{
get
{
Return
ConfigurationSettings.AppSettings ["Connectionstring"].
Tostring ();
}
}
}
} Unfortunately, the Configuration Block does not automatically provide this wrapper. 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 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 LOKEVER, WE Have Tried Several Third Party Menu and Toolbar Controls and All of Them Had Serious Bugs, EG
DotNetMagic (www.dotnetmagic.com) Docking panels did not implement enough events and it is unclear what the events are doingMenu control is OK DotNetBar (www.devcomponents.com) 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 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 directl y 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: Add The next 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 "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 Formus
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 InvalidMessageBox.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 Formus
Requestedform.focus ()
Application.run (mainform);
Else 'No Command Line Parameters, Just Show The Main Form
Application.run (new mainform ())
END IF
End Sub 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
MenuActionUndoBackCutRemember: Remember Text and Cursor PositionCut To Clipboard Return to Remembern / aSave RecordRemember old valuesExecute procCustomerSaveClose FormReturn to Old valuesReopen form Sample code to come in the SSW .NET Toolkit 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 Access 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. 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:
Lots of if statements (really messy - most people try this first) Interfaces (Implements statement in VB) Factory pattern? (Best - most flexible and extensible approach) 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 (eg 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)