10

MarkupExtension新しいオブジェクトを作成するためにXAMLからの非文字列パラメーターが必要なカスタムに取り組んでいます。DataContextスコープ内のフィールドで非文字列パラメーターバインディングを使用することは可能ですか?

言い換えれば、どうすればこのようなことができますか?

<ListBox ItemsSource="{Binding Source={local:MyMarkupExtension {x:Type Button},IncludeMethods={Binding Source=CustomerObject.IsProblematic}}}" />

ここでIncludeMethods=CustomerObject.IsProblematic私にこのエラーを与えます:

タイプ'TypeDescriptorExtension'の'IncludeMethods'プロパティにバインディングを設定することはできません。「バインディング」は、DependencyObjectのDependencyPropertyにのみ設定できます。

誰か助けてもらえますか?

ありがとう

4

4 に答える 4

13

「Binding」は、DependencyObject の DependencyProperty でのみ設定できます。これは true です。問題は、MarkupExtensionクラスがから派生していないことですDependencyObject。そのため、そのプロパティにバインディングを設定することはできません。

[編集]

回避策はValueConvertersを使用することです。もう 1 つの回避策は、多重継承を許可するように C# 言語を変更することです。ちなみに、SilverlightではインターフェースをMarkupExtension実装IMarkupExtensionしているので、カスタム拡張で実装してから派生させ、そこDependecyObjectに追加DependencyPropertyしてバインディングを設定しようとしました。クラッシュはしませんが、ProvideValue() が呼び出された後にバインディングが実際に設定されます。そのため、Silverlight でも解決策はありません (または難しい - Klaus78 の回答で提供されているリンクを参照してください)。WPF では、MarkupExtension はインターフェイスを実装していないため、そのプロパティにバインドできません。

于 2012-04-26T07:26:46.097 に答える
0

このリンクは約

バインド可能なプロパティを持つカスタムマークアップ拡張機能

編集WPFではMarkupExtensionがIMarkupExtensionインターフェイスを実装していないため、これはSilverlightでのみ機能することに注意してください。(ありがとうEvAlex)

于 2012-04-26T08:00:18.927 に答える
0

この問題の回避策を見つけました。
主なアイデアは、バインドが必要な各パラメーターの添付プロパティを定義することです。

public class MarkupExtensionWithBindableParam : MarkupExtension
{
    public BindingBase Param1 { get; set; } // its necessary to set parameter type as BindingBase to avoid exception that binding can't be used with non DependencyProperty

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        IProvideValueTarget target = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
        DependencyObject targetObject;
        DependencyProperty targetProperty;
        
        if (target != null && target.TargetObject is DependencyObject && target.TargetProperty is DependencyProperty)
        {
            targetObject = (DependencyObject)target.TargetObject;
            targetProperty = (DependencyProperty)target.TargetProperty;
        }
        else
        {
            return this; // magic
        }

        // Bind the Param1 to attached property Param1BindingSinkProperty 
        BindingOperations.SetBinding(targetObject, MarkupExtensionWithBindableParam.Param1BindingSinkProperty, Param1);

        // Now you can use Param1
        
        // Param1 direct access example:
        object param1Value = targetObject.GetValue(Param1BindingSinkProperty);
        
        // Param1 use in binding example:
        var param1InnerBinding = new Binding() { Source = targetObject, Path = new PropertyPath("(0).SomeInnerProperty", Param1BindingSinkProperty) }); // binding to Param1.SomeInnerProperty
        return param1InnerBinding.ProvideValue(serviceProvider); // return binding to Param1.SomeInnerProperty
    }

    private static DependencyProperty Param1BindingSinkProperty = DependencyProperty.RegisterAttached("Param1BindingSink", typeof(object)// set the desired type of Param1 for at least runtime type safety check
                       , typeof(MarkupExtensionWithBindableParam ), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits));
}

使い方は簡単です:

<TextBlock Text="{local:MarkupExtensionWithBindableParam Param1={Binding Path='SomePathToParam1'}}"/>
于 2016-06-06T22:37:13.950 に答える