ePlaice / For the Best Software on the Net

Mainly Free and Open Source Software


Software Dev't Navigation

Delphi Conversion | DataSets | DataGridView | Record Navigation | Data Formatting / Validation | Data Queries Data Input Form Data Readers MDI Forms Charts Using MySQL | MySQL NET Connector |

Valid XHTML 1.1

Latest news

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.

Links:

Formatting and Validating Data

SharpDevelop

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.

Formatting a TextBox

If you are displaying a non bound field in a textbox then I found the following worked well :-

Currency Field Display

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 :-

monthReceipts.Text String.Format("{0:£#,##0.00}", Convert.ToDecimal(m_accin))

Currency Field Update

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 :-

contentsRow[0]["pvalue"Double.Parse(textPValue.Text, System.Globalization.NumberStyles.Currency);

MaskedTextBox

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.

Dates and the MaskedTextBox

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.

Currency and the MaskedTextBox

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 :-

protected override void OnGotFocus(EventArgs e) 

base.OnGotFocus(e)
SelectionStart 0

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.

newItemRow["pvalue"maskedTextPValue.Value;

Formatting and Databinding

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.

Currency Conversion

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.

Binding CValueBinding = new Binding("Text", dsView, "contents.cvalue")
CValueBinding.Format += new ConvertEventHandler(this.textValue_FormatCurrency)
textCValue.DataBindings.Add(CValueBinding)

private void 
textValue_FormatCurrency(object sender, ConvertEventArgs e) 

// The method converts only to string type. Test this using the DesiredType. 
if(e.DesiredType != typeof(string)) return; 

// Use the ToString method to format the value as currency ("c"). 
e.Value ((double) e.Value).ToString("c")
}

Blob Conversion

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.

Binding notesBinding = new Binding("Text", dsView, "author.notes")
notesBinding.Format += new ConvertEventHandler(this.textBoxNotes_FormatBlob)
textBoxNotes.DataBindings.Add(notesBinding)
The following gives details of the Format Blob Routine 

private void textBoxNotes_FormatBlob(object sender, ConvertEventArgs e) 

Byte[] byteBLOBData 
= new Byte[0]
byteBLOBData (Byte[])e.Value
MemoryStream stmBLOBData = new MemoryStream(byteBLOBData)
e.Value System.Text.Encoding.UTF8.GetString(byteBLOBData)

Formatting DataGridView Cell

Formatting the data in a DataGridView Cell is reasonably straightforward :-

Displaying Currency

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.

dataGridView1.Columns["bal"].DefaultCellStyle.Format "c"

Data Validation

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.