2012-04-26 5 views
5

Ich arbeite an einer benutzerdefinierten MarkupExtension, in der ich einen non-string Parameter von XAML benötige, um das neue Objekt zu konstruieren. Ist es möglich, eine Nicht-String-Parameterbindung für ein Feld im Datenkontextbereich zu verwenden?MarkupExtension mit Bindungsparametern

Mit anderen Worten, wie kann ich so etwas tun?

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

wo IncludeMethods=CustomerObject.IsProblematic mir diesen Fehler geben: Die Bindung kann nicht auf der ‚IncludeMethods‘ Eigenschaft des Typs ‚TypeDescriptorExtension‘ gesetzt werden. Eine 'Bindung' kann nur für eine DependencyProperty eines DependencyObject festgelegt werden.

Kann mir jemand helfen?

dank

Antwort

9

A nur auf einem DependencyProperty eines DependencyObject eingestellt werden kann 'verbindlich' - es ist wahr. Das Problem ist, dass MarkupExtension Klasse nicht von DependencyObject abgeleitet wird, deshalb ist es nicht möglich, die Eigenschaften zu binden.

[EDIT]

Behelfslösung verwendet ValueConverters. Eine andere Problemumgehung besteht darin, C# -Sprache zu ändern, um Mehrfachvererbung zu ermöglichen. By the way, in Silverlight MarkupExtension implementiert IMarkupExtension Schnittstelle, so habe ich versucht, es in meiner benutzerdefinierten Erweiterung zu implementieren und leiten Sie es von DependecyObject, fügte hinzu DependencyProperty dort und verbindliche festlegen. Es stürzt nicht ab, aber die Bindung ist tatsächlich gesetzt nach ProvideValue() wird aufgerufen. Selbst in Silverlight gibt es keine Lösung (oder es ist schwierig - siehe Link in Klaus78's answer). In WPF implementiert MarkupExtension keine Schnittstelle, sodass Sie nicht an die Eigenschaften binden können.

+0

kann mir jemand empfehlen, eine Abhilfe? – user1351709

+0

siehe meine Bearbeitung – EvAlex

+17

Ändern der C# -Sprache, um mehrere Vererbung zu ermöglichen ist nicht genau das, was ich eine "Abhilfe" nennen würde;) –

0

Dieser Link ist informativ über

Custom Markup Extension with bindable properties

EDIT mir jemand beachten, dass dies nur für Silverlight funktioniert, weil in WPF Markupextension nicht IMarkupExtension Schnittstelle implementieren. (Danke EvAlex)

+0

Es funktioniert nur für Silverlight, weil in WPF MarkupExtension IMarkupExtension Schnittstelle nicht implementiert – EvAlex

-1

Ich habe eine Abhilfe für dieses Problem gefunden.
Die Grundidee besteht darin, für jeden Parameter, der eine Bindung erfordert, eine angehängte Eigenschaft zu definieren.

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

Die Verwendung ist einfach:

<TextBlock Text={local:MarkupExtensionWithBindableParam Param1={Binding Path="SomePathToParam1"}}/> 
+0

Es gibt ein Problem mit dem Beispiel * Usage *. Muss das Markup nicht in Anführungszeichen stehen? – OmegaMan

+1

scheint nicht zu funktionieren; param1Value ist immer null – esskar

Verwandte Themen