WPF资源部分中的DataContextProxy

5
我在我的WPF应用程序中使用DataContextProxy遇到了麻烦。当我将DataContextProxy放在Grid的资源部分时,它从未加载。如果我将DataContextProxy移出资源部分,则一切正常。
我已经调查了一段时间,并尝试了许多方法来调试应用程序。
- 我在我尝试使用代理的控件上放置了DebugConverter。Debug转换器从未被调用。 - 我使用WPFSnoop查看是否有任何绑定错误。在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') - 我在我的DataContextProxy的loaded事件上放置了断点。loaded事件从未被调用,我在DataContextChanged事件中放置了断点,但也从未被调用。
以下是一些示例代码以演示此问题。显然,我知道我实际上不需要在TextBox上使用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)
    {

    }

}
1个回答

2

我在尝试使用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"
        );
    }
}

你只需要将它附加到父元素即可。子元素中的静态资源引用将保持不变。我在这里发布了一个使用示例(链接)


1
我碰巧遇到了同样的问题,并在这里找到了Thomas Levesque的解决方案(发布在此处),即BindingProxy更为简洁。但是,你的帖子让我走上了正确的轨道,Arthur。谢谢! - Jan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接