Delphi Conversion | DataSets | DataGridView | Record Navigation | Data Formatting / Validation | Data Queries Data Input Form Data Readers MDI Forms Charts Using MySQL | MySQL NET Connector |
27 Feb 2007: I decided to write a few lines about my experiences with C# and SharpDevelop, but got waylaid looking at some of my earlier experiences.
07 Mar 2007: SharpDevelop 2.1 Final has been released.
When I was converting my applications from Delphi I found I was spending a large amount of time formatting data for display in forms.
All of this is pretty well documented but nevertheless I seemed to waste a lot of time in finding the best method of presenting the data. In some cases it seemed that use of the maskedtextbox would be beneficial, in other cases use of formatting events seemed best. So I decided to attempt to classify some of the more common occurrences to avoid keep on re-inventing the wheel. This will no doubt be added to as I go through future developments. I was also interested in data validation because my previous applications developed in Delphi mostly relied on 'live' database connections where the first you would know you had a problem was when there was a database error. Using disconnected datasets allows you to exercise much more control over data validation, but there is quite a lot of coding work involved initially.
If you are displaying a non bound field in a textbox then I found the following worked well :-
Here m_accin is defined as a string which is read from a query and is then required to be shown as decimal currency in a textbox field :-
Now you have your textbox filled with a decimal value and prefixed by a currency symbol and you wish to update. Of course the database update fails because of the currency symbol prefix, so you have to make a little conversion such as :-
When NET 2.0 was released there was quite a lot of excitement about how the MaskedTextBox would greatly assist data input and formatting. Unfortunately, this is only true to a limited extent, and I have found it useful on only a few occasions. There are a limited number of examples supplied as standard and it is possible to customise a mask but in practice I have found that the short date format is about the only one I use regularly. Even this is not ideal because if I am entering a date in short format (i.e. dd/mm/yyyy) I still have to supply a conversion to make the input date compatible with a database ISO date format.
I used the supplied date masks and was a little surprised that these did not perform any validation at all, for example you could enter a date of '22/75/0000' or even leave part of the date blank. However, when I looked at the Microsoft Developer Network website this was explained very well and there was a good example. So I decided to try a custom mask calling events as suggested. This works very well and gives as much flexibility in your validation as most people would ever need. It seems a bit of a shame that these weren't incorporated directly into the control. Never mind it has made me re-evaluate my approach to data validation.
I tried using the standard MaskedTextBox with a custom mask, but gave up after a few futile attempts. However, there seems to be at least one way forward by using a third party component called CurrencyMaskedTextBox. This works well but I still have one or two little problems such as ensuring the text cursor goes to the start of field. I fixed this by overriding the 'OnGetFocus' event in the CurrencyMaskedTextBox with a little bit of code as follows :-
Also when I update a value I would like the tab to select all the field contents so that it can be overwritten without the user having to position the cursor. The code project has an excellent article called Nullable Masked Edit which I then used some of the ideas in conjunction with CurrencyMaskedTextBox to get a reasonable solution. You can then use the Value property of the control to update the database field.
If you wish to format a field on a form which is bound to a database field then you have to call an event to format the data rather than attempting to format the textbox field directly.
The following shows how to create a new binding which is linked to the database field "contents.cvalue". A new ConvertEventHandler is created which calls textValue_FormatCurrency function. Note that this function can format and or parse the data before being displayed on the form.
To format the notes Blob, we need to process the format for the Notes text box. To accomplish this, we add our own event handlers to the Format event.
Formatting the data in a DataGridView Cell is reasonably straightforward :-
If you want a datagridview column to display currency use the DefaulCellStyle with a format of "c". This also avoids nasty rounding errors on doubles etc. and also prefixes the value with the local currency.
So far I spent a lot of time trying to format the data but very little on actually validating a Windows form. It soon became very tedious applying validation logic to the textbox focus events, not to mention the nightmare involved in ploughing through and maintaining all the code. So there has to be a better way maybe based on Business Object Validation - well I had a quick look at some articles and decided this was fine if I was building a large corporate database involving many analysts and coders. But there is only me, so I ruled this out and chose instead the much maligned method (by the purists) of validating at the presentation level i.e. the Windows form. In fact I came across a couple of validation controls which could do the simple tasks I wanted and eventually chose the Validator control which you can find at the Code Project website. I like this because for each Textbox you can specify the Datatype, whether it is required, specify a regular expression for validation and ranges on numerics. When you drop the validator control on your form each Textbox automatically gets some new validation properties and all you have to do is enter your specification. OK, you may also have to write some regular expression gibberish such as ^[A-Z][a-zA-Z0-9.,&\(\)\s-]{2,30}$ which I hope checks that the first character is uppercase alpha, the remaining characters can be alphanumeric or space, hyphen, ampersand, comma, open and close bracket and the string length must be between 2 and 30 characters long.