任何 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 中删除代理声明,因为它现在位于字典中。
- 您将无法更改
BindingProxy
的DataContext
,它将使用使用者 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>
快照:
您真的需要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/