【问题标题】:WPF DataContextProxy in resources section资源部分中的 WPF DataContextProxy
【发布时间】:2012-05-13 20:55:22
【问题描述】:

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

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

  • 我已在尝试使用的控件上放置了一个 DebugConverter 代理与。调试转换器永远不会被调用。

  • 我使用 WPFSnoop 查看是否有任何绑定错误。我明白了 在 DataContextProxy 上出现绑定错误,

    System.Windows.Data 错误:3:找不到提供 DataContext 的元素。 BindingExpression:(无路径);数据项=空;目标元素是“代理” (名称='');目标属性是“DataContext”(类型“对象”)

  • 我在 DataContextProxy 的加载事件上放置了一个断点。 加载的事件永远不会被调用,我在 永远不会调用的 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)
    {

    }

}

【问题讨论】:

    标签: c# wpf silverlight mvvm datacontext


    【解决方案1】:

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

    您只需要将它附加到父元素。子元素中的静态资源引用将保持不变。我已经发布了一个用法示例here

    【讨论】:

    • 我碰巧遇到了同样的问题,发现 Thomas Levesque 的解决方案 posted here 作为 BindingProxy 更脆一些。但是你的帖子帮助我走上了正轨,亚瑟。谢谢!
    猜你喜欢
    • 2010-10-14
    • 1970-01-01
    • 2011-04-08
    • 2014-06-14
    • 1970-01-01
    • 2013-10-23
    • 2011-12-27
    • 2012-07-07
    • 2017-12-03
    相关资源
    最近更新 更多