资源部分中的 WPF DataContextProxy

本文关键字:WPF DataContextProxy 资源部 | 更新日期: 2023-09-27 18:33:14

我在WPF应用程序中使用DataContextProxy时遇到问题。当我将 DataContextProxy 放在网格的 Resources 部分时,它永远不会加载。如果我将 DataContextProxy 移出资源部分,一切正常。

我已经对此进行了一段时间的调查,并尝试了许多方法来调试应用程序。

  • 我已经在我尝试使用的控件上放置了一个调试转换器代理。从不调用调试转换器。

  • 我使用 WPFSnoop 查看是否存在任何绑定错误。我得到在 DataContextProxy 上出现绑定错误后,

    System.Windows.Data 错误:3:找不到提供 DataContext 的元素。绑定表达式:(无路径(;数据项=空;目标元素是"代理"(名称=''(;目标属性为"数据上下文"(类型为"对象"(

  • 我已经在我的 DataContextProxy 的加载事件上放置了一个断点。永远不会调用加载的事件,我已经在DataContextChanged 事件,从不调用。

下面是一些示例代码来演示这一点。显然,我知道我真的不需要在文本框上使用DataContextProxy。

<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>

类 DataContextProxy

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)
    {
    }
}

资源部分中的 WPF DataContextProxy

当我尝试在WPF中使用DataContextProxy时,我也遇到了这个问题。我提出了一个受其启发的解决方案,该解决方案似乎可以很好地处理这项工作。看看吧:

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"
        );
    }
}

您只需要将其附加到父元素。子元素中的静态资源引用将保持不变。我在这里发布了一个使用示例。