如何从 ResourceDictionary 引用 BindingProxy 实例

Sin*_*atr 2 c# data-binding wpf

任何 wpf 程序员迟早都会开始使用BindingProxy

我试图通过将一些资源移动到单独的资源字典中来拆分 xaml。我的问题是资源包含对BindingProxy.

我该如何处理这种情况?

举个例子,假设有一个资源在BindingProxy某处使用

<Window.Resources>
    <local:BindingProxy x:Key="proxy" />
    <ControlTemplate x:Key="test">
        <TextBlock Text="{Binding DataContext.Test, Source={StaticResource proxy}}" />
    </ControlTemplate>
</Window.Resources>
<Control Template="{StaticResource test}" />
Run Code Online (Sandbox Code Playgroud)

和后面的代码

public partial class MainWindow : Window
{
    public string Test { get; set; } = "Test 123";

    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
    }
}
Run Code Online (Sandbox Code Playgroud)

它可能不是最好的例子,使用BindingProxy并不合理,但它很好地达到了演示目的。在运行时窗口中将"Test 123"显示文本。


现在让我们尝试将资源移动到资源字典中Dictionary1.xaml

<ResourceDictionary ... >
    <ControlTemplate x:Key="test">
        <TextBlock Text="{Binding Test, Source={StaticResource proxy}}"  /> <!-- error here -->
    </ControlTemplate>
</ResourceDictionary>
Run Code Online (Sandbox Code Playgroud)

并将主窗口资源更改为

<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Dictionary1.xaml" />
        </ResourceDictionary.MergedDictionaries>
        <local:BindingProxy x:Key="proxy" />
    </ResourceDictionary>
</Window.Resources>
<Control Template="{StaticResource test}" />
Run Code Online (Sandbox Code Playgroud)

会导致设计和运行时异常

System.Windows.Markup.XamlParseException:“为‘System.Windows.Markup.StaticResourceHolder’提供值引发了异常。” 行号“5”和行位置“20”。
内部异常
异常:找不到名为“proxy”的资源。资源名称区分大小写。

我该如何参考proxy?是否存在另一种技术来引用资源字典中的某些内容?也许有某种RelativeResource方法,但对于不在视觉树中的东西?由于明显的原因,我无法proxy进入ResourceDictionary1.xaml:它不会捕获DataContext窗口。

Luc*_*ain 5

尽管我不推荐BindingProxy在 MVVM 中使用,但我认为您的问题是这样解决的:

  • 请记住,当您ResourceDictionary在视图 XAML 中包含 时,它会自动继承视图的DataContext,因此您可以将 保留BindingProxy在 中ResourceDictionary,但需要显式指定绑定。
  • 请记住还要从 View XAML 中删除代理声明,因为它现在位于字典中。
  • DataContext您失去了更改的能力BindingProxy,它将使用DataContext消费者视图。

资源字典:

<ResourceDictionary ...>
    <!-- NOTE: Data property grabs the DataContext of the consumer view -->
    <local:BindingProxy x:Key="proxy" Data="{Binding}" />
    <ControlTemplate x:Key="text">
        <TextBlock Text="{Binding Data.Test, Source={StaticResource proxy}}" />
    </ControlTemplate>
</ResourceDictionary>
Run Code Online (Sandbox Code Playgroud)

窗户:

<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Dictionary1.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Window.Resources>
Run Code Online (Sandbox Code Playgroud)

快照:

在此输入图像描述


你真的需要吗BindingProxy

上面的建议违背了它的目的,BindingProxy因为它不再需要了;请注意,您可以ResourceDictionary按如下方式更改,它的工作原理完全相同,不需要任何BindingProxy

<ResourceDictionary ...>
    <ControlTemplate x:Key="test">
        <TextBlock Text="{Binding Test}" />
    </ControlTemplate>
</ResourceDictionary>
Run Code Online (Sandbox Code Playgroud)