2012-04-26 30 views
5

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

つまり、どうすればこのようにすることができますか? IncludeMethods=CustomerObject.IsProblematicは私に、このエラーを与える

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

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

誰でも手伝ってもらえますか?

おかげ

答えて

9

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

[EDIT]

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

+0

誰かが私に回避策を提案することができますか? – user1351709

+0

私の編集を参照してください – EvAlex

+17

複数の継承を許可するためにC#言語を変更することは、「回避策」とはまったく同じではありません;) –

0

このリンクは 誰かがWPF MarkupExtensionにIMarkupExtensionインタフェースを実装していないので、私は、これが唯一のSilverlightのために働くことに注意して作るEDIT

Custom Markup Extension with bindable properties

について有益です。 (ありがとうございますEvAlex)

+0

WPF MarkupExtensionがIMarkupExtensionインターフェイスを実装していないため、Silverlightのみで動作します – EvAlex

-1

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

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

* Usage *の例に問題があります。マークアップは引用符で囲む必要はありませんか? – OmegaMan

+1

は機能していないようです。 param1Valueは常にnullです。 – esskar