web-dev-qa-db-ja.com

リソースとしてのバインド

BindingResourceとして定義し、それを別のControlsプロパティで再利用できますか?

例:

製本:

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

XAMLでの再利用:

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

上記のようにBindingを宣言した後、エラーが発生しました。

「名前 'InitializeComponent'は現在のコンテキストに存在しません」

同じBindingを異なるコンテキストで再利用する方法はありますか?

17
Kylo Ren

あなたの質問に対する直接の答えは、「はい、バインディングをリソースとして定義できます」です。ここでの問題は、それをどのように利用するかということです。 1つの可能性は、リソースからバインディングをプルして適用する拡張クラスを作成することです。

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

使用例:

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

(...)

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

このソリューションはで使用できますかMultiBinding

はい、できます:

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

ただし、これには1つの欠点があります。すべてが実行時に機能しますが、XAML Designerは、BindingResourceExtensionMultiBinding.Bindingsコレクションに入れる適切なタイプ。しかし、ありがたいことに、簡単な解決策があります。代わりにStaticResourceExtensionを使用してください!したがって、これは実行時に機能的に同等ですが、設計者によって受け入れられます。

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

これがあなたが望むことを正確に行わないための2つの方法です:

1。カスタムマークアップ拡張機能の使用

短くするために、すべてのnullcheckなどをスキップしました。

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。PropertyPathをリソースにする

あなたのニーズに十分かもしれないし、そうでないかもしれません。

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