all groups > dotnet windows forms databinding > june 2006 >
You're in the

dotnet windows forms databinding

group:

2.0 Nullable Types won't Bind


2.0 Nullable Types won't Bind Paul
6/16/2006 5:42:50 PM
dotnet windows forms databinding:
Hello,

After some extensive tests, I believe I know why nullable types won't bind
correctly. It comes down to the way the Parse event needs to return the
value in the cevent.Value object. For example, if I have a class I want to
bind to:

public class Class1
{
private int? m_nullableInt;
public int? NullableInt
{
get { return m_nullableInt; }
set { m_nullableInt = value; }
}
}


and I bind it to a text box

Class1 a_class1 = new Class1();
Binding a_binding = new Binding("Text", a_class1, "NullableInt");
a_binding.Parse += new ConvertEventHandler(MyParse);
MyTextBox.DataBindings.Add(a_binding);

public void Parse(object sender, ConvertEventArgs cevent)
{
int? a_result = null;

if (cevent.Value is string && cevent.DesiredType.Equals(typeof(int?)))
try { a_result = Int32.Parse(cevent.Value); } catch {}

cevent.Value = a_result; // the int? gets cast down to an object,
either null if a_result is null, or a boxed int if it has a value, losing
its "int?" type.
}

Unfortunately, cevent.Value is of type object. If you assign an nullable
type to an object, it boxes it for you as the underlying type. When the
Parse returns to the .Net library, it is unable to call your set property
because it is of the wrong type (it is an int, not a int?, so it can't
successfully call the SetValue on the property).

If anyone has any ideas for workarounds, or if I am completely talking
rubbish, please let me know. I presume I am going to have to call the
SetValue in the Parse myself?


Thanks,

-Paul

Re: 2.0 Nullable Types won't Bind Chris Jobson
6/17/2006 11:14:52 PM
[quoted text, click to view]

I'm a bit puzzled as to what the problem is. Your code works fine for me
(after changing "a_result = Int32.Parse(cevent.Value);" to "a_result =
Int32.Parse(cevent.Value.ToString());" to make it compile) and the object
gets updated correctly with both integer values and null. The only issue I
can see is that if you enter a non-integer in the text box then the object's
property is set to null, and the data binding then erases the string in the
text box - which may not be what you want.

Could you post more details as to what isn't working.

Chris Jobson

Re: 2.0 Nullable Types won't Bind Paul
6/20/2006 10:01:32 AM

[quoted text, click to view]

Chris, thank you for looking at this with me. I am definately not seeing
the same thing as you. Whether or not I use my own Parse (I only added it
to be able to set a breakpoint to see what was happening), when I tab out of
the textbox after typing in a number, it reverts to a blank textbox. If I
set a breakpoint on Class1.set_NullableInt, it never breaks. If I take the
?s out of Class1's definitions, all works as advertised.

Here is the whole form code, you just need to add a textbox named textbox1
(yes, I had originally left out the string cast, as you noted. Also the
name of the Parse routine didn't match the one in the Event Handler set):


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace FirstApp
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Class1 a_class1 = new Class1();
Binding a_binding = new Binding("Text", a_class1, "NullableInt");
a_binding.Parse += new ConvertEventHandler(MyParse);
textBox1.DataBindings.Add(a_binding);
}
public void MyParse(object sender, ConvertEventArgs cevent)
{
int? a_result = null;
if (cevent.Value is string && cevent.DesiredType.Equals(typeof(int?)))
try { a_result = Int32.Parse((string)cevent.Value); } catch { }
cevent.Value = a_result;
}
}
public class Class1
{
private int? m_nullableInt;
public int? NullableInt
{
get { return m_nullableInt; }
set { m_nullableInt = value; }
}
}
}


Finally, as an example of what is going on under the hood, I wrote a couple
of lines of code to demonstrate the problem. There are 2 things going on:
1) The idea that a nullable type will lose its nullable-ness when boxed is
documented on MSDN:

http://msdn2.microsoft.com/en-us/ms228597.aspx

2) When you return the ConvertEventArgs.Value, if the types don't match
EXACTLY, then the binding code will not call the Set accessor.

int? a_nullableInt = 4;
// special case boxes the underlying, not the nullable.
object a_object = a_nullableInt;

// there is no set accessor which matches type "int", so a_propertyInfo will
be null
PropertyInfo a_propertyInfo = a_class1.GetType().GetProperty("NullableInt",
a_object.GetType());
if (a_propertyInfo != null)
a_propertyInfo.SetValue(a_class1, a_object, null);

If you take the a_object.GetType() out of the call to GetProperty, and just
get it by name, the code will get a property info back, and the call to
SetValue actually works. But I am willing to guess that MS made sure that
the type was specified in GetProperty() in the binding code to protect
against an exception right off the bat (which is the case when types do not
match -- try passing a UInt32 to SetValue() on an Int32 property --, but
GetType() on a nullable returns the underlying type, since GetType() forces
the nullable into a box, so they can't throw an exception, and they let it
through).

Please let me know if you are still not seeing the same thing.

Thanks for your time,

-Paul

Re: 2.0 Nullable Types won't Bind Paul
6/20/2006 1:26:17 PM

[quoted text, click to view]

I did some more research (better refined googles) and came up with someone's
solution to this. In essence, it is what I proposed, that is, to call
SetValue directly in the parse.

http://blog.urbanguru.net/?p=3

I still would be interested as to why you did not see this problem yourself,
however.

-Paul

Re: 2.0 Nullable Types won't Bind Paul
6/20/2006 3:58:33 PM

[quoted text, click to view]

That is pretty weird. It works, but I can't even find decent documentation
on what that parameter does. MSDN says, "optionally enables formatting to
be applied". What is that supposed to mean? And why does it affect
parsing?

But it sure is a lot less code than the solution that guy gave, above in my
previous note.

Thanks for your help.

-Paul

Re: 2.0 Nullable Types won't Bind Chris Jobson
6/20/2006 7:06:28 PM
[quoted text, click to view]

<snip>

[quoted text, click to view]

I've just noticed one difference in my code: when I create the binding I do
Binding a_binding = new Binding("Text", a_class1, "NullableInt", true);
i.e. set the FormattingEnabled parameter to true (force of habit, as this is
what VS does if you do the bindings through the properties window). If I
remove the ", true" then I get the same result as you. I've no idea why this
should make a difference, but maybe it's worth your trying it to see what
happens.

Chris Jobson

Re: 2.0 Nullable Types won't Bind Paul
6/20/2006 9:11:39 PM

[quoted text, click to view]

I miss the days when the C Runtime source was available, and you could solve
puzzles like these simply by reading the code. This flag sounds like a bit
of a hack to me, but I'll take it. Thanks again for your help.

Re: 2.0 Nullable Types won't Bind Chris Jobson
6/20/2006 9:37:32 PM
[quoted text, click to view]

Glad that it works for you too! I've just been reading "Data Binding With
Windows Forms 2.0" by Brian Noyes, and his description of this parameter is
"A flag to indicate whether to automatically format the displayed values ...
in general this should always be turned on". There's then a bit more in a
later chapter about "automatic formatting and parsing" which is a bit too
long to quote, but it appears that if the flag is set "the .NET framework is
going to try to do everything possible to come up with a sensible
conversion". When I've got more time I might try using Reflector to try and
work out what's going on, but in the meantime it seems safe enough to always
set the flag.

Chris

AddThis Social Bookmark Button