odd Bindings

  • Thread starter Thread starter Samuel
  • Start date Start date
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".
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 editor control:

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

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

public DateTime Value
{
get
{
return _value;
}
set
{
if (value == _value) return;
_value = value;
...
if (ValueChanged != null) ValueChanged(this, EventArgs.Empty);
}
}

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 this time 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 method listening (ValueChanged is not
null), which 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? Maybe the bindings have problems with
value/reference types? 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.

Samuel, from Spain
 
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
bound 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".
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 editor control:

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

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

public DateTime Value
{
get
{
return _value;
}
set
{
if (value == _value) return;
_value = value;
...
if (ValueChanged != null) ValueChanged(this, EventArgs.Empty);
}
}

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 this time 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 method listening (ValueChanged is not
null), which 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? Maybe the bindings have problems with
value/reference types? 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.

Samuel, from Spain
 
Back
Top