2012-05-04 141 views
4

我在使用WPF应用程序中的DataContextProxy时遇到了麻烦。当我将一个DataContextProxy放置在一个Grid的Resources部分时,它永远不会被加载。如果我将DataContextProxy移出资源部分,那么所有工作都可以正常进行。WPF DataContextProxy在资源部分

我一直在调查这一段时间,并尝试了很多方法来调试应用程序。

  • 我放置在我试图使用 代理与控制DebugConverter。调试转换器永远不会被调用。

  • 我用WPFSnoop来查看是否有任何绑定错误。我在DataContextProxy上发现绑定错误 ,

    System.Windows.Data错误:3:找不到提供DataContext的元素。 BindingExpression:(no path);的DataItem = NULL;目标元素是'代理' (Name ='');目标属性是'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) 
    { 

    } 

} 

回答

1

我也打这个问题时,我试图用DataContextProxy在WPF。我想出了一个受它启发的解决方案,它似乎很体面地处理工作。检查出来:

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