2012-04-26 11 views
5

Sto lavorando su un MarkupExtension personalizzato in cui ho bisogno di parametri non stringa da XAML per costruire il nuovo oggetto. È possibile utilizzare un binding di parametri non stringa su un campo in ambito datacontext?MarkupEstensione con parametri di binding

In altre parole, come posso fare qualcosa di simile?

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

dove IncludeMethods=CustomerObject.IsProblematic darmi questo errore: vincolante non può essere impostato sulla proprietà 'IncludeMethods' di tipo 'TypeDescriptorExtension'. Un 'Binding' può essere impostato solo su una DependencyProperty di DependencyObject.

Qualcuno può aiutarmi?

grazie

risposta

9

A 'Binding' può essere impostato solo su un DependencyProperty di DependencyObject - è vero. Il problema è che la classe MarkupExtension non deriva da DependencyObject, ecco perché non è possibile impostare il binding sulle sue proprietà.

[EDIT]

Soluzione sta usando ValueConverters. Un'altra soluzione alternativa consiste nel cambiare il linguaggio C# per consentire l'ereditarietà multipla. A proposito, in Silverlight MarkupExtension implementa l'interfaccia IMarkupExtension, quindi ho provato a implementarlo nella mia estensione personalizzata e derivarlo da DependecyObject, aggiunto DependencyProperty lì e impostare il binding ad esso. Non si arresta in modo anomalo, ma il binding viene effettivamente impostato dopo Viene chiamato ProvideValue(). Quindi, anche in Silverlight non c'è soluzione (o è difficile - vedi link fornito in Klaus78's answer). In WPF MarkupExtension non implementa alcuna interfaccia, quindi non puoi associarti alle sue proprietà.

+0

Qualcuno mi può suggerire una soluzione? – user1351709

+0

vedere la mia modifica – EvAlex

+17

Cambiare il linguaggio C# per consentire l'ereditarietà multipla non è esattamente ciò che chiamerei una "soluzione";) –

0

Questo collegamento è ben informato su

Custom Markup Extension with bindable properties

EDIT Qualcuno mi fa notare che questo funziona solo per Silverlight, perché in WPF MarkupExtension non implementa l'interfaccia IMarkupExtension. (Grazie a EvAlex)

+0

Funziona solo per Silverlight, perché in WPF MarkupExtension non implementa l'interfaccia IMarkupExtension – EvAlex

-1

Ho trovato una soluzione per questo problema.
L'idea principale è definire la proprietà associata per ogni parametro che richiede il binding.

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

L'uso è semplice:

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

C'è un problema con l'esempio * Usage *. Il markup non deve essere tra virgolette? – OmegaMan

+1

non sembra funzionare; param1Value è sempre nullo – esskar

Problemi correlati