views:

544

answers:

2

I have an interesting data binding question related to combobox. Hope someone has some good suggestion.

I have a simple form, it contains a file picker and a comboxbox. Every time a file is picked, I read a list of strings from the file to a List object and I set comboBox.DataSource = listOfStrings.

In the form load event, I set comboBox.DataBindings.Add("SelectedItem", myObject, "PickedValue");

The purpose is clear: every time a string is selected from the combobox, I want to write the string to myObject.PickedValue.

That is the whole story.

Now I launch the form, rather than go pick a file, I check the combobox first. Of course, at this point, comboBox.DataSource is null, comboBox.SelectedItem is null, too. But the data binding on the comboBox is already setup (since the setting is in form load event). Now my focus cannot be moved from the combobox to anywhere else.

I think the reason is, when I try to check the combobox, it has null as SelectedItem. When I try to move the focus to somewhere else, the data binding of the combobox is triggered. Underlying, it tries to convert the selected item to string and update myObject.PickedValue with that converted string. Since you cannot convert a null to a string, the data binding validation fails, and the validation mechanism doesn't allow my focus to be moved elsewhere and I am sucked at this moment, cannot even move to pick a file.

My question is, what is the normal binding setup work-flow for my application scenario to prevent this trap? What is the correct order of setting up such a data binding so I can check my combobox before its data source is filled by something?

FYI, I tried to bind myObject.PickedValue to SelectedText property of the combobox (I noticed that SelectedText is a string and never be null, even when SelectedItem is null). But interestingly, even if I select something from the combobox, SelectedText is still empty string when data binding is triggered. What's wrong here?

Thanks for any help.

+1  A: 

This doesn't seem right; it should be possible to set a string property to null. Possibly the focus problem lies elsewhere. Have you tried setting a breakpoint on your property setter to confirm your theory?

The SelectedText property of a combo box refers to text that has been selected in the text portion of the combobox. This only works if the dropdown style is set to combo. Basically it's the selected text of the text box portion of the combo control (the reason a combobox is called "combo" is because it is a combination of a textbox and a selection list). You would ordinarily expect this property to be empty unless the user was editing the text portion of the combo.

If you want a workaround for this problem that is consistent with a good user experience, try disabling the combo box on form load, then enabling it when a file is picked.

Paul Keister
Thanks for giving me a workaround solution. I think the idea of disabling the combobox till it is ready is a good idea. And thanks for explaining why SelectedText property doesn't work for me. I guess I will take it as the answer.
Steve
+2  A: 

The failure is a little simpler than you describe: Your ComboBox will fail just because there is no selected item, because there's nothing to select from.

I would just disable the ComboBox if there's nothing to select from. It's pretty easy to do. Remember to hook up a PropertyChanged event in your data object; the binding source will find it automatically with reflection.

class MyData
{
    public event PropertyChangedEventHandler PropertyChanged;

    // ...
    public HasListOfStrings { get { return ListOfStrings != null && 0 < ListOfStrings.Count; } }

    private void LoadListOfStrings
    {
        // ... load the list of strings ...

        if ( PropertyChanged) {
            PropertyChanged(this, "ListOfStrings");
            PropertyChanged(this, "HasListOfStrings");
        }
    }
}

In the designer, bind the 'Enabled' property of the 'ComboBox' to the HasListOfStrings property. You can do it in code with:

listOfStringsComboBox.Bindings.Add ("Enabled", bindingSource, "HasListOfStrings");

I also recommend you change the AutoValidate property of the container (or container's container) to EnableAllowFocusChange.

XXXXX
Thanks Larry for the workaround. The idea is similar to Paul's and thank you particular for the code. I took his as the answer just because he answered my SelectedText question as well. But basically yours is as helpful as his. Cheers.
Steve
Glad I could help!
XXXXX