Windows Forms' Binding system bugs?

S

Samuel

Hello:

I first put the code and then I'll comment it:

.... somewhere in Form_Load ...

Binding binding = new Binding("Value", myTableDataView, "StartupDate");
binding.Format = new ConvertEventHandler(StartupDateBinding_Format);
StartupDateDateTimePicker.DataBindings.Add(binding);

....

private void StartupDateBinding_Format(object sender, ConvertEventArgs e)
{
if (e.Value == null || e.Value == DBNull.Value)
e.Value = new DateTime(2003, 1, 1);
}

....

The problem comes when I do:
((CurrencyManager)BindingContext[myTableDataView]).AddNew();

The StartupDateBinding_Format method is not called, and an exception is
thrown which says "DataBinding could not find a row in the list that is
suitable for all bindings".
Of course it couldn't find a row suitable for all bindings, because my
StartupDateBinding_Format method has not been called, and it cannot set the
DateTime Value property of a DateTimePicker object to null or DBNull.

And also I'm having trouble creating my own date control:

public class DateTimeEditBox : System.Windows.Forms.TextBox
{
private DateTime _value;

public DateTimeEditBox()
{
DataBindings.CollectionChanged += new
CollectionChangeEventHandler(DataBindings_CollectionChanged);
}

[Bindable(true), Browsable(true), Description("The date and time value
shown in the control.")]
public DateTime Value
{
get
{
return _value;
}
set
{
if (value == _value) return;
_value = value;
...
if (ValueChanged != null) ValueChanged(this, EventArgs.Empty);
}
}

[Category("Property Changed"), Description("Occurs when the value of the
property Value has changed.")]
public event EventHandler ValueChanged;

private void DataBindings_CollectionChanged(object sender,
CollectionChangeEventArgs e)
{
if (e.Action == CollectionChangeAction.Add)
((Binding)e.Element).Format += new
ConvertEventHandler(Binding_Format);
}

private void Binding_Format(object sender, ConvertEventArgs e)
{
if (e.Value == null || e.Value == DBNull.Value)
e.Value = new DateTime(2003, 1, 1);
}
}

Well this control has the Format event handler embedded so I don't need to
do a "binding.Format = new ConvertEventHandler(StartupDateBinding_Format);",
but it's the same.

But surprisingly the Binding_Format method is called and it works fine. BUT
when I change the Value property, the value in the bounded row doesn't
change, even when I'm raising ValueChanged. And I checked that when I raise
ValueChanged there is one listening method (ValueChanged is not null), which
must be (well, I can confirm, *it is*) the handler method generated by the
Binding.

No exception is thrown, nothing. And it should work because the column which
I bound is a DateTime DataColumn.

Why all this strange behavior? Have Microsoft tested the binding system
before they released the .NET framework? Or am I doing something wrong (I
don't think so, but...)?

By the way, I'm using Visual Studio .NET 2003 / .NET Framework 1.1.

Thank you in advance.
 
S

Samuel

I already solved it, what a stupid and also curious thing!!

Previosly I said: "BUT when I change the Value property, the value in the
bounded row doesn't change, even when I'm raising ValueChanged.".

I was (and also I am) changing the Value property in the OnValidating method
(my control derives from TextBox control, so what I was doing is):

protected override OnValidating(CancelEventArgs e)
{
DateTime newValue;
try { newValue = DateTime.Parse(Text) }
catch
{
e.Cancel = true;
return;
}

Value = newValue;
OnValidated(e); // <-- This is wrong, it should be OnValidating(e);
}

Accidentally I wrote OnValidated(e), and the Validating event was never
raised.
When I corrected this the bound row changed when I typed a new date / time
in the box.

So it seems that the Binding doesn't change the bound object's property when
the bound Control's property changes, also it waits until the Validating
event of the bound Control is raised.

I hope I made myself understood.

It is a really curious thing, and I think is great, but also I think it
should be documented in the Binding class' help.

Samuel, from Spain (please forgive me if I made any mistake writing in
english).

Samuel said:
Hello:

I first put the code and then I'll comment it:

... somewhere in Form_Load ...

Binding binding = new Binding("Value", myTableDataView, "StartupDate");
binding.Format = new ConvertEventHandler(StartupDateBinding_Format);
StartupDateDateTimePicker.DataBindings.Add(binding);

...

private void StartupDateBinding_Format(object sender, ConvertEventArgs e)
{
if (e.Value == null || e.Value == DBNull.Value)
e.Value = new DateTime(2003, 1, 1);
}

...

The problem comes when I do:
((CurrencyManager)BindingContext[myTableDataView]).AddNew();

The StartupDateBinding_Format method is not called, and an exception is
thrown which says "DataBinding could not find a row in the list that is
suitable for all bindings".
Of course it couldn't find a row suitable for all bindings, because my
StartupDateBinding_Format method has not been called, and it cannot set the
DateTime Value property of a DateTimePicker object to null or DBNull.

And also I'm having trouble creating my own date control:

public class DateTimeEditBox : System.Windows.Forms.TextBox
{
private DateTime _value;

public DateTimeEditBox()
{
DataBindings.CollectionChanged += new
CollectionChangeEventHandler(DataBindings_CollectionChanged);
}

[Bindable(true), Browsable(true), Description("The date and time value
shown in the control.")]
public DateTime Value
{
get
{
return _value;
}
set
{
if (value == _value) return;
_value = value;
...
if (ValueChanged != null) ValueChanged(this, EventArgs.Empty);
}
}

[Category("Property Changed"), Description("Occurs when the value of the
property Value has changed.")]
public event EventHandler ValueChanged;

private void DataBindings_CollectionChanged(object sender,
CollectionChangeEventArgs e)
{
if (e.Action == CollectionChangeAction.Add)
((Binding)e.Element).Format += new
ConvertEventHandler(Binding_Format);
}

private void Binding_Format(object sender, ConvertEventArgs e)
{
if (e.Value == null || e.Value == DBNull.Value)
e.Value = new DateTime(2003, 1, 1);
}
}

Well this control has the Format event handler embedded so I don't need to
do a "binding.Format = new ConvertEventHandler(StartupDateBinding_Format);",
but it's the same.

But surprisingly the Binding_Format method is called and it works fine. BUT
when I change the Value property, the value in the bounded row doesn't
change, even when I'm raising ValueChanged. And I checked that when I raise
ValueChanged there is one listening method (ValueChanged is not null), which
must be (well, I can confirm, *it is*) the handler method generated by the
Binding.

No exception is thrown, nothing. And it should work because the column which
I bound is a DateTime DataColumn.

Why all this strange behavior? Have Microsoft tested the binding system
before they released the .NET framework? Or am I doing something wrong (I
don't think so, but...)?

By the way, I'm using Visual Studio .NET 2003 / .NET Framework 1.1.

Thank you in advance.
 

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