2
votes

I'm having an annoying problem with WPF binding. Basically, I declare a FrameworkElement in my UserControl's resources, but that item doesn't seem to get notified when the DataContext of the parent UserControl changes.

Basically, in my UserControl I have a Popup in the ItemTemplate for an ItemsControl. In that Popup, I needed to bind to something in the parent view's ViewModel, so I came up with what I thought was a clever trick. Taking a cue from CollectionViewSource, I figured I'd just bind my parent's view model to a resource, and then use that resource to get to the ViewModel from the DataTemplate, like so:

    <UserControl.Resources>
        <cont:ViewModelSource Source="{Binding}" x:Key="ParentViewModel"/>
    </UserControl.Resources>

So that later I can use it like:

CommandParameter="{Binding ViewModel.OpenEntity, Source={StaticResource ParentViewModel}}"

This all would seem to work except that the DataContext on the ViewModelSource doesn't get reset when the DataContext of the UserControl gets reset. Right now, I'm making this work hackily: setting the resource's DataContext in code-behind on the UserControl's DataContextChanged event.

I took a look in Reflector to see how CollectionViewSource does this, but it doesn't seem to be doing anything special.

Anyone know why this is happening or how I can fix it?

2

2 Answers

2
votes

I had the same problem and I found a solution.

First i tryed to set my ViewModel as DataContext of my root element. wrong.

Then i tryed to set my ViewModel as Resource and set binding source of my root element to the Resource. wrong.

Finally I created a IValueConverter to convert a Model (witch is DataContext of the control) to a ViewModel. Then I Bind DataContext of my root element with the converter.

<UserControl.Resources>

    <local:PersonToControllerConverter x:Key="PersonToControllerConverter"/>

    <!--<local:PersonController x:Key="controller"
        Value="{Binding}"
        Parent="{Binding Path=DataContext,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type TreeViewItem}}}"
        />-->

</UserControl.Resources>



<Border x:Name="root" BorderBrush="Black" BorderThickness="2" >
    <Border.DataContext>
        <MultiBinding Converter="{StaticResource PersonToControllerConverter}">
            <Binding/>
            <Binding Path="DataContext" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type TreeViewItem}}"/>
        </MultiBinding>
    </Border.DataContext>

    <!--DataContext="{Binding Source={StaticResource controller}}">-->

    <!--<Border.DataContext>
        <local:PersonController
                    Value="{Binding}"
                    Parent="{Binding Path=DataContext,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type TreeViewItem}}}"
                    />
    </Border.DataContext>-->

I think that when the DataContext breaks the binding in an element, when the datacontext changes on a root element, it stops on the broken binding.

1
votes

Maybe you have to create a middle object that implement INotifyPropertyChanged interface.