views:

70

answers:

3

I'm beginning with WPF and binding, but there are some strange behavior that I don't understand.

Exemple 1 : A very simple WPF form, with only one combobox (name = C) and the following code in the constructor :

    public Window1()
    {
        InitializeComponent();

        BindingClass ToBind = new BindingClass();
        ToBind.MyCollection = new List<string>() { "1", "2", "3" };

        this.DataContext = ToBind;

        //c is the name of a combobox with the following code :  
        //<ComboBox Name="c" SelectedIndex="0" ItemsSource="{Binding Path=MyCollection}" />
        MessageBox.Show(this.c.SelectedItem.ToString());
    }

Can you explain me why this will crash because of this.c.SelectedItem being NULL.

So I though ... no problem it's because it's in the constructor, let's put the code in the Loaded form event :

        public Window1()
    {
        InitializeComponent();
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        BindingClass ToBind = new BindingClass();
        ToBind.MyCollection = new List<string>() { "1", "2", "3" };
        this.DataContext = ToBind;
        MessageBox.Show(this.c.SelectedItem.ToString());
    }

Same problem this.c.SelectedItem is null...

Remark : If I remove the Messagebox thing, then the binding work fine, I have the value in the combobox. It's like if "some" time was needed after the datacontext is set. But how to know when the binding will be done ?

Tx you for your help.

A: 

Your binding happens during the Window_Loaded event but it's not drawn to scren so there isn't a SelectedItem yet.

You will have to listen to the PropertyChanged event of your Binding or DataContext or whatever. Then OnPropertyChanged, bring up your messagebox

masenkablast
+2  A: 

It is because the selectionchanged has not triggered yet so selecteditem is still null.

private void c_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
   MessageBox.Show(this.c.SelectedItem.ToString());
}

If you are new to WPF I suggest you go and have a look at the MVVM pattern. There is a really nice introduction video here: http://blog.lab49.com/archives/2650

Michael
Hell, In fact it is even more than just the selecteditem, that is null. The combobox is reacting like if it was not bind at all (items being null also).Was curious because this is working in silverlight 3
Fabian
Yea, didn't bother checking that :P.Kinda weird that it works in silverlight but not in wpf. Maybe they have a different way of loading controls.I checked the OnContentRendered and MyCollection has been set before it renders the control itself.I don't have the time atm to look more into it but the red gates .net reflector is a great tool to look at whats going on in the .net framework. Helped me found a lot of strange things with WPF.Sorry about the wrong answer, but I hope you take a look at MVVM as its a really nice pattern to develop WPF applications.
Michael
Tx you Michael, I'm moving a project form silverlight 3 to WPF, at first glance it seems to be quite easy, but they are really nasty strange differences between them that make the thing quite complicated ! :)
Fabian
Just an other small question, in general where do you bind the viewmodel in your view (wpf form) ? You pass the interface of the viewmodel to the WPF form constructor ?
Fabian
np, good to know as I might be moving some WPF apps to silverlight soon. Where I bind the viewmodel kinda depends. Sometime i pass it in the constructor especially when I use IOC. But sometimes I create the viewmodel first, then the window and set the viewmodel to the datacontext of the window. I guess its up to what you prefer.
Michael
A: 

Tx for the comment, it should be something like this, I try this, and this is working :

    BindingClass ToBind = new BindingClass();
    public Window1()
    {
        InitializeComponent();
        ToBind.MyCollection = new List<string>() { "1", "2", "3" };

        this.DataContext = ToBind;
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        MessageBox.Show(this.c.SelectedItem.ToString());
    }

So here, even if it is not drawn on the screen the selecteditem is already fetched ... very strange.

Fabian