c# - 如何从 ResourceDictionary 引用 BindingProxy 实例
问题描述
任何 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: ''在 'System.Windows.Markup.StaticResourceHolder' 上提供值引发了异常。' 行号“5”和行位置“20”。
内部异常
异常:找不到名为“代理”的资源。资源名称区分大小写。
我该如何参考proxy
?是否存在另一种技术来引用资源字典中的某些内容?也许某种RelativeResource
方法,但对于不在视觉树中的东西?由于显而易见的原因,我无法proxy
进入ResourceDictionary1.xaml
:它不会捕获DataContext
窗口。
解决方案
尽管我不推荐BindingProxy
在 MVVM 中,但我认为您的问题是这样解决的:
- 请记住,当您
ResourceDictionary
在视图 XAML 中包含 a 时,它会自动继承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>
窗户:
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
快照:
你真的需要BindingProxy
吗?
上面的建议违背了它的目的,BindingProxy
因为它不再需要了;请注意,您可以更改ResourceDictionary
如下,它的工作原理完全相同,无需任何BindingProxy
:
<ResourceDictionary ...>
<ControlTemplate x:Key="test">
<TextBlock Text="{Binding Test}" />
</ControlTemplate>
</ResourceDictionary>
推荐阅读
- c# - 如何在 _layout 中设置 cookie
- python - 我可以在 Python 的正则表达式中使用变量而不是常量吗
- mysql - 该字符串包含由连字符('-')分隔的多个子字符串。如何比较子字符串并删除重复的子字符串?
- maven - 如何关闭 intelij idea maven run debug console 的右侧分成两部分?
- ios - 基于用户在 ToDo DatePicker (Swift & SwiftUI) 中设置的日期时间的 iOS 本地通知
- google-cloud-firestore - 无法从 firestore 创建名为“timestamp”的字段的架构列
- javascript - 在 Quasar (vue) 中使用解析从数据中获取数据 - 返回未定义
- javascript - 远程通知不会触发notificationclick
- docker - 如何在来宾操作系统和 Docker 容器之间绑定目录?
- php - Symfony 实体属性访问问题 无法确定访问类型