5

I’m having trouble using a DataContextProxy in my WPF application. When I place a DataContextProxy in the Resources section of a Grid it is never loaded. If I move the DataContextProxy out of the resource section everything works correctly.

I’ve been investigating this for some time and have tried a number of methods to debug the application.

  • I’ve placed a DebugConverter on the control that I’m trying to use the Proxy with. The Debug converter is never called.

  • I’ve used WPFSnoop to see if there are any binding errors. I get the following binding error on the DataContextProxy,

    System.Windows.Data Error: 3 : Cannot find element that provides DataContext. BindingExpression:(no path); DataItem=null; target element is 'Proxy' (Name=''); target property is 'DataContext' (type 'Object')

  • I’ve placed a breakpoint on the loaded event of my DataContextProxy. The loaded event is never called and I’ve placed a breakpoint in the DataContextChanged event which is never called.

Here is some sample code to demonstrate this. Obviously I know I do not really need to use a DataContextProxy on the TextBox.

<Window x:Class="WpfDataContextProxyBug.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfDataContextProxyBug"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <local:DebugConverter x:Key="DebugConverter"/>
    </Window.Resources>
    <Grid>
        <Grid.Resources>
            <local:Proxy x:Key="Proxy" DataContext="{Binding}" />
        </Grid.Resources>

    <TextBox DataContext="{Binding Path=Name, Source={StaticResource Proxy}, Converter={StaticResource DebugConverter}}"/>
    </Grid>
</Window>

The DataContextProxy class

public class Proxy : FrameworkElement
{
    public Proxy()
    {
        Loaded += DataContextProxy_Loaded;
        DataContextChanged += Proxy_DataContextChanged;
    }

    void Proxy_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
    {

    }

    void DataContextProxy_Loaded(object sender, RoutedEventArgs e)
    {

    }

}
chrism233
  • 97
  • 10

1 Answers1

2

I've also hit this problem when I tried to use the DataContextProxy in WPF. I've come up with a solution inspired by it which seems to handle the job pretty decently. Check it out:

public class DataContextProxyBehavior : Behavior<FrameworkElement>
{
    public Object DataSource
    {
        get { return (Object)GetValue(DataSourceProperty); }
        set { SetValue(DataSourceProperty, value); }
    }
    public static readonly DependencyProperty DataSourceProperty =
        DependencyProperty.Register("DataSource", typeof(Object), typeof(DataContextProxy), null);

    protected override void OnAttached()
    {
        base.OnAttached();

        // Binds the target datacontext to the proxy,
        // so whenever it changes the proxy will be updated
        var binding = new Binding();
        binding.Source = this.AssociatedObject;
        binding.Path = new PropertyPath("DataContext");
        binding.Mode = BindingMode.OneWay;
        BindingOperations.SetBinding(this, DataContextProxyBehavior.DataSourceProperty, binding);

        // Add the proxy to the resource collection of the target
        // so it will be available to nested controls
        this.AssociatedObject.Resources.Add(
            "DataContextProxy",
            this
        );
    }
    protected override void OnDetaching()
    {
        base.OnDetaching();

        // Removes the proxy from the Resources
        this.AssociatedObject.Resources.Remove(
            "DataContextProxy"
        );
    }
}

You just need to attach it to the parent element. The static resource reference in the child element will remain the same. I've posted an usage example here.

Community
  • 1
  • 1
Arthur Nunes
  • 6,718
  • 7
  • 33
  • 46
  • 1
    I just happend to have the same problem and found Thomas Levesque's solution [posted here](https://thomaslevesque.com/2011/03/21/wpf-how-to-bind-to-data-when-the-datacontext-is-not-inherited/) as BindingProxy a little crispier. But your posting helped me on the right track, Arthur. Thanks! – Jan Jun 07 '19 at 20:13