Databindings and invalid values being displayed

C

Claire

Hi,
I have a form with 3 textboxes.
My code is below (short working example from vs 2005).
The value "_cm" is the only stored data, km and miles are calculated values.
The text boxes work fine until an invalid value is entered. In that case,
the incorrect value is displayed in the text box rather than the correct
value stored in _cm.
I wanted to use this method in my "real" application for conversions between
km/miles but I can't get it to work.
What am I doing wrong please?
Claire


public partial class Form1 : Form
{
int _cm = 1000;
public int Cm
{
get {
return _cm;
}
set {
if ((value >= 0)&&(value <= 20000))
_cm = value;
}
}
public double km
{
get
{
return _cm / 100000.0f;
}
set
{
Cm = (int)(value * 100000.0f);
}
}
public double miles
{
get
{
return _cm * 0.000006213711922373339;
}
set
{
Cm = (int)(value / 0.000006213711922373339);
}
}
public Form1()
{
InitializeComponent();
textBox1.DataBindings.Add(new Binding("Text", this, "Cm", true,
DataSourceUpdateMode.OnValidation, null, "N3"));
textBox2.DataBindings.Add(new Binding("Text", this, "miles", true,
DataSourceUpdateMode.OnValidation, null, "N3"));
textBox3.DataBindings.Add(new Binding("Text", this, "km", true,
DataSourceUpdateMode.OnValidation, null, "N3"));
}
}
 
M

Marc Gravell

If the value is no goo, throw an exception:

if (value < 0 || value > 20000)
throw new ArgumentOutOfRangeException();

This will prevent entry of an invalid value.

Marc
 
C

Claire

Thank you for answering.
This doesnt seem to work. I get 2 possible results, either the cursor stays
in the field I entered data into (and I can't close the applciation or move
the cursor to another field.) or I get no error.
In either case, my newly entered value remains, formatted in N format.
I traced into the code, the exception was thrown as expected, then nothing
Ive disabled all error reporting in exceptions options.

set {
if ((value >= 0) && (value <= 20000000))
_cm = value;
else
throw new ArgumentOutOfRangeException();
}
 
M

Marc Gravell

Note that you might be able to do things here involving various
combinations of IDataErrorInfo, INotifyPropertyChanged and
TypeConverter... so how do you want it to behave? Somebody puts in an
invalid value... then what?
 
C

Claire

Marc Gravell said:
Note that you might be able to do things here involving various
combinations of IDataErrorInfo, INotifyPropertyChanged and
TypeConverter... so how do you want it to behave? Somebody puts in an
invalid value... then what?

I want the value converting back to the original value, without the user
being stopped from tabbing out.

I've found the problem seems to be associated to the format specifier
version of the binding constructor
"textBox3.DataBindings.Add(new Binding("Text", this, "km", true,
DataSourceUpdateMode.OnValidation, null, "N3"));"

If I use a non formatted binding eg
"textBox3.DataBindings.Add(new Binding("Text", this, "km")"
and dont use the exception, the underlying _cm value replaces the invalid
new number in the textbox.
On the other hand, if I use the binding constructor that uses formatting
"N3", the text box displays the formatted wrong value rather than the
underlying _cm value.

The easiest way to get around this is to use the shorter constructor, but I
know that people will complain that they only want to see 1 or 2 decimal
places in the text box.
 
C

Claire

For archive purposes.
The cause of the problem is that whatever value was typed into the text box
is formatted and displayed BEFORE a failed validation.
To fix this, use the following style of construct and code. The
ConvertEventHandler is called after validation rather than before, so the
correct bound value is displayed.

public int Distance_cm
{
get
{
return _Profile.Distance;
}
set
{
// Validate
if (value < MinDistance) value = MinDistance;
if (value > MaxDistance) value = MaxDistance;
_Profile.Distance = value;
}
}

public double Distance_meters
{
get
{
return Distance_cm * meters_Multiplier;
}
set
{
Distance_cm = value / meters_Multiplier;
}
}

protected void FloatFormat0(object sender, ConvertEventArgs e)
{
e.Value = string.Format("{0:N0}", e.Value);
}

private void Setter()
{
Binding binding = new Binding("Text", this, "Distance_meters", false,
DataSourceUpdateMode.OnValidation, null, null);
binding.Format += new ConvertEventHandler(FloatFormat0);
DistText_meters.DataBindings.Add(binding);
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top