2012-05-04 3 views
4

У меня возникли проблемы с использованием DataContextProxy в моем приложении WPF. Когда я помещаю DataContextProxy в раздел «Ресурсы» Grid, он никогда не загружается. Если я переведу DataContextProxy из раздела ресурсов, все будет работать правильно.WPF DataContextProxy в разделе ресурсов

Я изучал это в течение некоторого времени и попробовал несколько методов для отладки приложения.

  • Я поместил DebugConverter на контроль, что я пытаюсь использовать прокси с. Конвертер Debug никогда не вызывается.

  • Я использовал WPFSnoop, чтобы увидеть, есть ли какие-либо ошибки привязки. Я получаю после ошибки привязки к DataContextProxy,

    Ошибка System.Windows.Data: 3: Не удается найти элемент, предоставляющий DataContext. BindingExpression: (нет пути); DataItem = NULL; целевой элемент - «Прокси» (Name = ''); target свойство «DataContext» (тип «Объект»)

  • Я разместил точку останова в загруженном событии моего DataContextProxy. Загруженное событие никогда не вызывается, и я поместил точку останова в событие DataContextChanged, которое никогда не вызывается.

Вот пример кода для демонстрации этого. Очевидно, я знаю, что мне действительно не нужно использовать DataContextProxy в TextBox.

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