5

WPF アプリケーションで DataContextProxy を使用すると問題が発生します。Grid の Resources セクションに DataContextProxy を配置すると、ロードされません。DataContextProxy をリソース セクションの外に移動すると、すべてが正しく機能します。

私はこれをしばらく調査しており、アプリケーションをデバッグする方法をいくつか試しました。

  • プロキシを使用しようとしているコントロールに DebugConverter を配置しました。デバッグ コンバーターは呼び出されません。

  • WPFSnoop を使用して、バインド エラーがあるかどうかを確認しました。DataContextProxy で次のバインド エラーが発生します。

    System.Windows.Data エラー: 3: DataContext を提供する要素が見つかりません。BindingExpression:(パスなし); DataItem=null; ターゲット要素は 'Proxy' (Name='') です。ターゲット プロパティは 'DataContext' (タイプ 'Object') です

  • 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)
    {

    }

}
4

1 に答える 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"
        );
    }
}

親要素にアタッチするだけです。子要素の静的リソース参照は変わりません。こちらに使用例を掲載しました。

于 2012-11-19T18:40:47.140 に答える