2011-02-02 8 views
5

¿Hay alguna forma de establecer una propiedad adjunta a través de un estilo?WPF: ¿Puedo definir/establecer una propiedad adjunta a través de un estilo?

Tengo, por ejemplo, un botón en el que se establece la materia Interacción (de System.Windows.Interactivity)

<Button> 
    <i:Interaction.Triggers> 
    ... 
    </i:Interaction.Triggers> 
</Button> 

Ahora me gustaría hacer un estilo en el que dicha propiedad se establece Interaction.Triggers, sustituyendo así las redundancias por tener que especificar que la propiedad en cada instancia de Button. ¿Es esto posible en WPF?

<Style Target={x:Type Button}> 
    <!-- ??? --> 
    <Setter PropertyName="i.Interaction.Triggers"> 
    ... 

De alguna manera no puedo ver cómo, pero he visto otros ejemplos en la web en la que las propiedades asociadas parecen ser accesible desde el interior de un estilo ...

actualización

Así Básicamente, esto es más bien un problema con Interaction. Los Tiggers no tienen una forma de "establecer" algo. ¿Cómo se supone que debo reutilizar un conjunto de definiciones de interacción?

+0

duplicado posibles: http://stackoverflow.com/questions/4067876/set-hidden-attachedproperty-through-style – flq

Respuesta

8

Este es un problema conocido con propiedades de solo lectura (lo mismo con la colección InputBindings). Para resolver este problema he creado una propiedad adjunta:

public static StyleTriggerCollection GetTriggers(DependencyObject obj) { 
    return (StyleTriggerCollection)obj.GetValue(TriggersProperty); 
} 

public static void SetTriggers(DependencyObject obj, StyleTriggerCollection value) { 
    obj.SetValue(TriggersProperty, value); 
} 

public static readonly DependencyProperty TriggersProperty = 
    DependencyProperty.RegisterAttached("Triggers", typeof(StyleTriggerCollection), typeof(ControlExtensions), new UIPropertyMetadata(null, OnTriggersChanged)); 

static void OnTriggersChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { 
    var triggers = (StyleTriggerCollection) e.NewValue; 

    if (triggers != null) { 
     var existingTriggers = Interaction.GetTriggers(d); 

     foreach (var trigger in triggers) { 
      existingTriggers.Add((TriggerBase)trigger.Clone()); 
     } 
    } 
} 

Esta propiedad utiliza StyleTriggerCollection costumbre, porque la recolección de disparo estándar tiene constructor no pública:

public class StyleTriggerCollection : Collection<TriggerBase> 
{ 
} 

en la incubadora estilo que se puede utilizar como esto:

<Setter Property="my:ControlExtensions.Triggers"> 
    <Setter.Value> 
     <my:StyleTriggerCollection> 
      <!-- Put your triggers here --> 
     </my:StyleTriggerCollection> 
    </Setter.Value> 
</Setter> 
+0

Eso parece muy prometedor, voy a hav ¡eche un vistazo tan pronto como regrese al código! – flq

+1

Esto parece funcionar, pero estoy confundido en cuanto al uso de un DataContext en los desencadenadores. Parece que no puedo hacer que RelativeSource AncestorType etc. funcione ... – flq

+0

Necesita comprender cómo funciona la fuente relativa. Funciona en elementos que están en el árbol visual. En este caso, los factores desencadenantes no están en el árbol visual: la colección de desencadenantes es solo una propiedad de un elemento en el árbol visual. La razón por la cual la herencia del contexto de datos funciona en este caso es que Triggers hereda Freezable. Puede leer sobre esto aquí: http://drwpf.com/blog/category/freezables/ –

Cuestiones relacionadas