2012-05-04 64 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