如何从ResourceDictionary引用BindingProxy实例 [英] How to reference BindingProxy instance from ResourceDictionary

查看:40
本文介绍了如何从ResourceDictionary引用BindingProxy实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

迟早任何WPF程序员都开始使用


您真的需要 BindingProxy 吗?

上面的建议破坏了 BindingProxy 的目的,因为它不再需要了.请注意,您可以按照以下方式更改 ResourceDictionary ,它的工作原理完全相同,而无需 BindingProxy :

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

Sooner or later any wpf programmer begin to use BindingProxy.

I am trying to split xaml by moving some of resources into separate resource dictionary. My problem is that resources contain reference to BindingProxy.

How can I handle this situation?

As an example, lets say there is a resource with BindingProxy which is used somewhere

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

and code behind

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

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

It may not be the best example, using BindingProxy is not really justified, but it serve demonstration purpose well. During run-time window with text "Test 123" will be shown.


Now lets try move resource to resource dictionary Dictionary1.xaml

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

and change main window resource to

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

will lead to desinger and run-time exception

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.

How can I reference proxy? Is there another technique exist to reference somethining from resource dictionary? Maybe some kind of RelativeResource approach but for things which are not in visual tree? I can't move proxy into ResourceDictionary1.xaml for obvious reasons: it will not capture DataContext of window.

解决方案

Even though I don't recommend the BindingProxy in MVVM, this is how I think your problem is resolved:

  • Bear in mind when you include a ResourceDictionary in your view XAML, it automatically inherits the DataContext of the view hence you can keep the BindingProxy in the ResourceDictionary but you need to specify the binding explicitly.
  • Remember to also remove the proxy declaration from the View XAML as it is now in the dictionary.
  • You lose the ability to change the DataContext of the BindingProxy, it will use the DataContext of the consumer view.

ResourceDictionary:

<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:

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

Snapshot:


Do you really need the BindingProxy?

The suggestion above defeats the purpose of the BindingProxy as it is not needed anymore; note you could just change the ResourceDictionary as follows and it works exactly the same without any need of the BindingProxy:

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

这篇关于如何从ResourceDictionary引用BindingProxy实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆