views:

42

answers:

2

I haven't really done a two way binding project before, so this might be a simple question.

I have an business object with all the right interfaces (INotifyPropertyChanged, etc...). I bound a Int32 property called CPP to a textbox named txtCPP via a BindingSource. The rules state that if CPP is less than 0, the text box should be blank, otherwise should display a value.

So to make that happen, I changed the property from Int32 to Int32? (nullable) and when the backing variable of the CPP property is less than zero, I actually return null.

This actually works fine with the UI. The problem comes when I want to persist the business object to the database. An external method takes the business object, reads its properties (including CPP) and persists them to the database. And obviously, instead of CPP being -1, it is being written as null.

I am sure I am not the first person to come up with this issue when doing two-way binding projects. How does one typically handle these problems in a clean way without polluting the form code with edge cases like that?

A: 

You could use the StringFormat property for the binding like this (Note that it is actually a bit hacky, because the Text Property of the TextBlock will display " " instead of an empty String when it encounters a value less than or equals 0):

<TextBlock Text="{Binding StringFormat={}{0:#; ; }}" />

The format String contains three parts. Also Note that the leading {} are for escaping purposes:

  1. The format before the first semicolon is for values > 0
  2. The format between the first and the second semicolon is for values < 0
  3. The format after the second semicolon is for values == 0

If you really need an empty String in the bound property, the best way would be to create your own Converter.

mpistrich
I like your solution, but he posted with a Winforms tag. I think he needs a winform solution and not a WPF one. (I started my response the same way <g>)
JMarsch
Oh, missed that tag, my mistake. Fortunately your answer coveres the problem for winforms. (At least I am not the only one who missed that tag at first ;))
mpistrich
+3  A: 

It sounds as though your rule about the box being blank is a UI rule, and not a data rule (so the data value really is -1, it just should be displayed as blank).

If that's the case, lets move the blank logic into the UI. So, your data object property returns an int (and it returns the real value of the int), and then you can morph it in your display.

One way to do that would be with formatting -- you can specify a Formatter with your databinding, or you can hook the Format event on the databinding.

Of course, you still need to decide what to do when the user enters a blank value into the textbox...

Here's a really simple-minded example, using the Format event in the databinding:


var binding = this.textBox1.DataBindings.Add("Text", MyObject, "AValue", true);
binding.Format += (s, args) =>
    {
        int i = (int)args.Value;
        if (i <= 0)
        args.Value = "";
    };

JMarsch
I added a formattingEnabled parameter to the Bindings setup, otherwise it does not work.
AngryHacker
Really? Just curious, what version of .net were you using? I actually ran that code in VS 2010/.net 4.0 before I posted and it worked. Weird.
JMarsch
@JMarsch VS2008.
AngryHacker