c# - 如何从 ResourceDictionary 引用 BindingProxy 实例

标签 c# wpf data-binding

任何 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}" />

以及背后的代码

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

    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
    }
}

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


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

<ResourceDictionary ... >
    <ControlTemplate x:Key="test">
        <TextBlock Text="{Binding Test, Source={StaticResource proxy}}"  /> <!-- error here -->
    </ControlTemplate>
</ResourceDictionary>

并将主窗口资源更改为

<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Dictionary1.xaml" />
        </ResourceDictionary.MergedDictionaries>
        <local:BindingProxy x:Key="proxy" />
    </ResourceDictionary>
</Window.Resources>
<Control Template="{StaticResource test}" />

会导致设计和运行时异常

System.Windows.Markup.XamlParseException: ''Provide value on 'System.Windows.Markup.StaticResourceHolder' threw an exception.' Line number '5' and line position '20'.'
Inner Exception
Exception: Cannot find resource named 'proxy'. Resource names are case sensitive.

如何引用代理?是否存在另一种技术来引用资源字典中的内容?也许某种 RelativeResource 方法,但对于不在可视化树中的东西?由于显而易见的原因,我无法将 proxy 移动到 ResourceDictionary1.xaml 中:它不会捕获窗口的 DataContext

最佳答案

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

  • 请记住,当您在 View XAML 中包含 ResourceDictionary 时,它会自动继承 View 的 DataContext,因此您可以保留 BindingProxy > 在 ResourceDictionary 中,但您需要显式指定绑定(bind)。
  • 请记住,还要从 View XAML 中删除代理声明,因为它现在位于字典中。
  • 您将无法更改 BindingProxyDataContext,它将使用使用者 View 的 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>

窗口:

<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Dictionary1.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Window.Resources>

快照:

enter image description here


您真的需要BindingProxy吗?

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

<ResourceDictionary ...>
    <ControlTemplate x:Key="test">
        <TextBlock Text="{Binding Test}" />
    </ControlTemplate>
</ResourceDictionary>

关于c# - 如何从 ResourceDictionary 引用 BindingProxy 实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65072899/

相关文章:

c# - 通过其他应用程序的窗口设置wpf窗口的所有者,可以吗?

c# - WPF - 绑定(bind)到 ListView 项中的列表

c# - System.Drawing.Icon 构造函数抛出 "Operation completed successfully"异常

c# - MonoTouch : Where is Frame. 来源?

C# 将剪贴板内容粘贴到 Excel 工作表中

c# - 在 ASP.NET MVC 中安全和 "squarified"照片上传

c# - 不使用代码隐藏从文本框中删除 'None'

c# - Visual C# .net 2013 和线程操作指南

c# - 如何使用子绑定(bind)中的父内容控件?

wpf - 绑定(bind)到表达式