wpf 作为资源绑定

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36912216/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 13:46:47  来源:igfitidea点击:

Binding as a Resource

wpfxamlwpf-controlsresourcedictionary

提问by Kylo Ren

Can I define a Bindingas a Resourceand then reuse it with different Controlsproperties?

我可以将 a 定义Binding为 aResource然后将其用于不同的Controls属性吗?

Example:

例子:

Binding:

捆绑:

<Window.Resources>        
    <Binding x:Key="MyBinding" Path="MyProperty" Mode="TwoWay" />
</Window.Resources>

Reuse in XAML:

在 XAML 中重用:

<TextBox Text="{StaticResource MyBinding}" />

After declaring Bindingas above I got the error:

Binding如上所述声明后,我收到错误:

"The name 'InitializeComponent' does not exist in the current context"

“当前上下文中不存在名称‘InitializeComponent’”

Is there any way to reuse the same Bindingin different contexts?

有没有办法Binding在不同的上下文中重用相同的内容?

采纳答案by Grx70

Direct answer to your question is "yes, you can define a binding as a resource". The problem here is how do you then make any use of it? One possibility is to create an extension class which would pull the binding from the resources and apply it:

您的问题的直接答案是“是的,您可以将绑定定义为资源”。这里的问题是你如何使用它?一种可能性是创建一个扩展类,该类将从资源中提取绑定并应用它:

public class BindingResourceExtension : StaticResourceExtension
{
    public BindingResourceExtension() : base() { }

    public BindingResourceExtension(object resourceKey) : base(resourceKey) { }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        var binding = base.ProvideValue(serviceProvider) as BindingBase;
        if (binding != null)
            return binding.ProvideValue(serviceProvider);
        else
            return null; //or throw an exception
    }
}

Usage example:

用法示例:

<Window.Resources>
    <ResourceDictionary>
        <Binding x:Key="MyBinding" Path="MyProperty" Mode="TwoWay" />
    </ResourceDictionary>
</Window.Resources>

(...)

<TextBox Text="{ns:BindingResource MyBinding}" />

Can this solution be used inMultiBinding?

该解决方案可以用于MultiBinding吗?

Yes, it can:

是的,它可以:

<TextBlock>
    <TextBlock.Text>
        <MultiBinding StringFormat="First: {0}, Second: {1}">
            <Binding Path="SomeProperty" />
            <ns:BindingResource ResourceKey="MyBinding" />
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>

There is however one drawback to this - although everything will work in run-time, the XAML Designerwill complain that BindingResourceExtensionis not of proper type to be put in the MultiBinding.Bindingscollection. But, thankfully, there is a quick solution - simply use StaticResourceExtensioninstead! So this, while being functionally equivalent in run-time, will be accepted by the designer:

然而,这样做有一个缺点——尽管一切都可以在运行时运行,但XAML 设计器会抱怨BindingResourceExtension放入MultiBinding.Bindings集合中的类型不正确。但是,值得庆幸的是,有一个快速的解决方案 - 只需使用即可StaticResourceExtension!因此,虽然在运行时功能等效,但设计人员将接受:

<TextBlock>
    <TextBlock.Text>
        <MultiBinding StringFormat="First: {0}, Second: {1}">
            <Binding Path="SomeProperty" />
            <StaticResource ResourceKey="MyBinding" />
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>

回答by Johan Larsson

Here are two ways to not do exactly what you want:

这里有两种方法可以不完全按照您的意愿行事:

1. Using a custom markup extension

1. 使用自定义标记扩展

Skipped all nullchecks etc. to keep it short.

跳过所有空检查等以保持简短。

using System;
using System.Windows;
using System.Windows.Data;
using System.Windows.Markup;

public class BindingDefinition
{
    public PropertyPath Path { get; set; }

    public BindingMode Mode { get; set; }
}

[MarkupExtensionReturnType(typeof(BindingExpression))]
public class ApplyBindingDefinition : MarkupExtension
{
    public BindingDefinition Definition { get; set; }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        var binding = new Binding
        {
            Path = this.Definition.Path,
            Mode = this.Definition.Mode
        };
        return binding.ProvideValue(serviceProvider);
    }
}


<Window.Resources>
    <local:BindingDefinition x:Key="MyProperty"
                             Mode="TwoWay"
                             Path="MyProperty" />
</Window.Resources>
<TextBox>
    <TextBox.Text>
        <!--  using element style here as the parser chokes on parsing nested markupextensions  -->
        <local:ApplyBindingDefinition Definition="{StaticResource MyProperty}" />
    </TextBox.Text>
</TextBox>

2. Making the PropertyPath a resource

2. 使 PropertyPath 成为资源

May or may not be enough for your needs.

可能满足您的需求,也可能不够。

<Window.Resources>
    <PropertyPath x:Key="MyPropertyPath">MyProperty</PropertyPath>
</Window.Resources>
...
<TextBox Text="{Binding Path={StaticResource MyPropertyPath}}" />