In WPF, perché TemplateBinding non funziona dove funziona Binding?




controltemplate propertychanged (2)

TemplateBinding non supporta l'associazione bidirezionale, solo Binding lo fa. Anche con l'opzione BindsTwoWayBeDefault, non supporta l'associazione a due vie.

Maggiori informazioni possono essere trovate here , ma per riassumere:

Tuttavia, TemplateBinding può trasferire i dati solo in una direzione: dal modello principale all'elemento con TemplateBinding. Se hai bisogno di trasferire i dati nella direzione opposta o in entrambi i modi, un Binding con RelativeSource di TemplatedParent è la tua unica opzione. Ad esempio, l'interazione con un TextBox o Slider all'interno di un modello modificherà una proprietà sul genitore basato su modelli solo se si utilizza un Binding a due vie.

Ok ... questo mi sta lasciando grattarmi la testa. Ho due controlli WPF: uno è un controllo utente e l'altro è un controllo personalizzato. Chiamiamoli UserFoo e CustomFoo. Nel modello di controllo per CustomFoo, utilizzo un'istanza di UserFoo, che è una parte denominata, in modo che possa accedervi dopo l'applicazione del modello. Funziona bene

Ora sia UserFoo sia CustomFoo hanno una proprietà Text definita su di essi (indipendentemente, cioè non un DP condiviso che utilizza AddOwner. Non chiedere ...) che sono entrambi dichiarati in questo modo ...

public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
    "Text",
    typeof(string),
    typeof(UserFoo), // The other is CustomFoo
    new FrameworkPropertyMetadata(
        null,
        FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
        null,
        null,
        true,
        UpdateSourceTrigger.PropertyChanged
    )
);

Si noti specificamente che la modalità è impostata su TwoWay e che UpdateSourceTrigger è impostato su PropertyChanged, sempre per entrambi.

Quindi, nel modello di stile per CustomFoo, voglio associare la proprietà Text di CustomFoo come origine alla proprietà Text di UserFoo interna. Normalmente, questo è facile. Basta impostare la proprietà di testo di UserFoo su "{TemplateBinding Text}" ma per qualche motivo va solo in un modo (cioè UserFoo è impostato correttamente da CustomFoo, ma non viceversa), anche se entrambi i DP sono impostati a due vie! Tuttavia, quando si utilizza un binding di fonte relativa anziché un binding di template, funziona alla grande! Um ... cosa ??

// This one works
Text="{Binding Text, RelativeSource={RelativeSource AncestorType={local:CustomFoo}}, Mode=TwoWay}"

// As does this too...
Text="{Binding Text, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"

// But not this one!
Text="{TemplateBinding Text}"

Quindi cosa dà? Cosa mi manca?


Trovato questo post sul forum su MSDN: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/0bb3858c-30d6-4c3d-93bd-35ad0bb36bb4/

Dice questo:

Un TemplateBinding è una forma ottimizzata di un Binding per scenari di template, analogo a un Binding costruito con

{Binding RelativeSource={RelativeSource TemplatedParent}}.

Nota da OP: contrariamente a ciò che dice nella documentazione, in realtà, dovrebbe essere questo ...

{Binding RelativeSource={RelativeSource TemplatedParent} Mode=OneWay}. 

Ho presentato un reclamo contro i documenti, e mentre hanno aggiunto una frase affermando che sono sempre a senso unico, l'esempio di codice continua a non elencare la modalità, ma immagino sia meglio di niente.)

TemplateBinding trasferisce i dati dal modello principale alla proprietà associata al modello. Se è necessario trasferire i dati nella direzione opposta o in entrambe le direzioni, creare un collegamento con RelativeSource di TemplatedParent con la proprietà Mode impostata su OneWayToSource o TwoWay.

Ulteriori informazioni in: http://msdn.microsoft.com/en-us/library/ms742882.aspx

Sembra che Mode = OneWay sia una delle "ottimizzazioni" dell'uso di TemplateBinding





templatebinding