2011-06-28 8 views
7

Estoy intentando convertir algunas de mis habilidades de WPF a Silverlight, y me he encontrado con un problema un tanto extraño en la mini aplicación de prueba en la que he estado trabajando. En WPF, me acostumbré a usar DataTriggers dentro de un estilo para establecer propiedades de control basadas en las propiedades de los datos encuadernados. He descubierto que algunos conjuntos relacionados con Blend le permiten hacer algo como esto en Silverlight, y se me ocurrió algo similar, en el que tengo los siguientes espacios de nombres declarados:Silverlight DataTrigger no dispara con carga

xmlns:ia="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions" 
xmlns:iv="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 


<DataTemplate x:Key="testItemTemplate"> 
     <StackPanel Orientation="Horizontal"> 
      <TextBox Text="{Binding Name, Mode=TwoWay}" x:Name="thing"/>     
      <iv:Interaction.Triggers> 
       <ia:DataTrigger Binding="{Binding Name}" Value="ReddenMe" Comparison="Equal"> 
        <ia:ChangePropertyAction TargetName="thing" PropertyName="Foreground" Value="Red"> 
        </ia:ChangePropertyAction> 
       </ia:DataTrigger> 
      </iv:Interaction.Triggers> 
     </StackPanel> 
    </DataTemplate> 

En este ejemplo, Tengo un objeto de datos que implementa INotifyPropertyChanged y genera el evento PropertyChanged como de costumbre para la propiedad Name. Obtengo el comportamiento esperado si cambio el valor del cuadro de texto y pierdo el foco, pero si el valor inicial del cuadro de texto está configurado en ReddenMe (que para este ejemplo artificial estoy usando como disparador para que el texto sea rojo), el texto no se pone rojo ¿Alguien sabe lo que está pasando aquí? Para DataTriggers en WPF, el disparador se disparará inmediatamente para cualquier dato.

Me doy cuenta de que podría usar un convertidor aquí, pero puedo pensar en situaciones en las que me gustaría usar disparadores, y me pregunto si hay algo que pueda hacer para que esto funcione.

+0

Hola ... a prueba su dilema y tiene el mismo problema. Lamentablemente, esto es lo que ocurre cuando, como usted, bajamos de WPF a Silverlight y debajo: o (No sé si existe una solución, pero creé un convertidor para hacer el trabajo y funcionó con los valores iniciales. – NestorArturo

+0

Gracias para ese NestorArturo: sí, después de publicar esto, traté de lograr lo mismo con un convertidor, y parecía hacer lo que yo buscaba. Sería interesante escuchar lo que piensan los gurús de WPF/Silverlight sobre los méritos de la separación conversores vs enfoques puramente basados ​​en XAML. Para cosas como mostrar/ocultar controles, siempre he encontrado que el enfoque de DataTrigger es un poco más transparente, aunque supongo que se podría argumentar que al tener un convertidor, terminas con un contenido menos desordenado markup al final. – andrewmcc

+0

Puede estar viendo este comportamiento porque DataTrigger se deriva de PropertyChangeTrigger y en su caso la propiedad Name no está cambiando inicialmente. O podría ser un error. Podría usar el reflector .net para echar un vistazo al DataTri la implementación de gger para confirmar. He usado DataTriggers antes, pero no me he encontrado con este problema, probablemente debido al hecho de que utilizo Visual State Manager y comienzo con el estado predeterminado. Una forma de intentar forzar el comportamiento deseado es establecer el valor del nombre después de cargar XAML. – Denis

Respuesta

11

Aquí está a solution que encontré en el blog de Tom Peplow: hereda de DataTrigger, y haz que el desencadenador evalúe la condición cuando se carga su elemento asociado.

Así es como se puede codificarlo:

public class DataTriggerEvaluateOnLoad : Microsoft.Expression.Interactivity.Core.DataTrigger 
{ 
    protected override void OnAttached() 
    { 
     base.OnAttached(); 
     var element = AssociatedObject as FrameworkElement; 
     if (element != null) 
     { 
      element.Loaded += OnElementLoaded; 
     } 
    } 

    protected override void OnDetaching() 
    { 
     base.OnDetaching(); 
     var element = AssociatedObject as FrameworkElement; 
     if (element != null) 
     { 
      element.Loaded -= OnElementLoaded; 
     } 
    } 

    private void OnElementLoaded(object sender, RoutedEventArgs e) 
    { 
     EvaluateBindingChange(null); 
    } 
} 
+0

¡Gracias! Estuve luchando con este hoy. – Aligned

+0

Esto es tan útil ... – Craig

Cuestiones relacionadas