views:

461

answers:

1

I've been going round in circles with this for a couple of days, and I'm hoping a WPF guru can see where I'm going wrong.

I'm setting CurrentViewModel in code. The Selected item of my ListBox and the Content of my ContentControl bind correctly. But when changing the selected item in the Listbox via the UI the CurrentViewModel is being set but the Content Control is not being updated.

I'm using a data template to map my Views and View Models.

    <DataTemplate DataType="{x:Type ViewModel:MyViewModel}">
       <View:MyView />
    </DataTemplate>

I have a ListBox which is bound to an observable collection of ViewModels. The Selected Item is bound to the current view model.

 <ListBox ItemsSource="{Binding MyViewModelCollection}" DisplayMemberPath="DisplayName" SelectedItem="{Binding CurrentViewModel, Mode=TwoWay}"/>

I also have a content control that is also bound to the CurrentView Model

 <ContentControl Content="{Binding CurrentViewModel, Mode=TwoWay}"/>

This is the property that they are both bound to

        public MyViewModel CurrentViewModel
    {
        get
        {
            return _currentViewModel;
        }
        set
        {
            if (_currentViewModel== value) return;

            _currentViewModel= value;
            OnPropertyChanged("CurrentViewModel");
        }
    }

I've edited the names for clarity and removed formatting information.

Any help greatly appreciated.

Cheers,

Daniel

EDIT: Came across the link How can I debug WPF bindings?. I set a break point on the Content binding and it does indeed only get called once when the binding is first set.

+3  A: 

You should not be setting TwoWay as the mode on your ContentControl:

<ContentControl Content="{Binding CurrentViewModel, Mode=OneWay}"/>

This is because you intend your ContentControl to read the value, but never write it.


As an aside, you can also bind the ContentControl to the currently selected item in the collection, rather than to that property by doing this:

<ListBox ItemsSource="{Binding MyViewModelCollection}" 
         DisplayMemberPath="DisplayName" 
         IsSynchronizedWithCurrentItem="True"/>

<ContentControl Content="{Binding MyViewModelCollection/}"/>

The "slash" (/) at the end of the collection indicates the current item selected in the collection and setting that current item property is as simple as setting the IsSynchronizedWithCurrentItem equal to true.

A lot of times I find with this combination, I really don't need the extra property on my view model.

Anyway, I hope this helps.

Anderson Imes
Thanks for your suggestions, i set the binding on the content back to one way. This is what it was originally, i think i set it to two way just to test if it had any effect.I tried the alternate method of binding and the same behavior remains. The initial binding is set OK but changing the listbox doesn't update the content.
Spruce
I made a sample that looks exactly like your post and it seems to work. Are you sure your setter on your property is firing? I think you might have something else going on.Try doing the same thing with just a simple collection of strings. Get back to basics and check your assumptions. Using the collection of strings will eliminate the datatemplating as a problem. It could be your datatemplate isn't quite right.
Anderson Imes
Thanks for your help. I did the same with a sample and got it to work. Went back to my main app, the problem was to do with how the Regions were being activated. Still not sure of why it would work once. Thanks again.
Spruce