2009-05-07 16 views
19

He creado un control de usuario, similar a lo siguiente:desencadenantes miembros de la colección deben ser del tipo EventTrigger

<UserControl> 
    <StackPanel Orientation="Vertical"> 

     <StackPanel x:Name="Launch" Orientation="Horizontal" Visibility="Collapsed"> 
      <!-- Children here --> 
     </StackPanel> 

     <ToggleButton x:Name="ToggleLaunch" IsChecked="False" Content="Launch" /> 

    </StackPanel> 
</UserControl> 

que he estado tratando de utilizar un DataTrigger para hacer el 'lanzamiento' StackPanel se hacen visibles cuando la ToggleButton está marcado y, de lo contrario, seguirá colapsado. Sin embargo, en tiempo de ejecución me aparece un error que dice "Inicialización fallida del objeto (ISupportInitialize.EndInit). Los elementos de la colección Triggers deben ser del tipo EventTrigger". Intenté agregarlo a la colección de disparadores de UserControl y StackPanel sin éxito. Mi gatillo XAML tiene el siguiente aspecto:

<DataTrigger Binding="{Binding ElementName=ToggleLaunch, Path=IsChecked}" Value="True"> 
    <Setter TargetName="Launch" Property="UIElement.Visibility" Value="Visible" /> 
</DataTrigger> 

Respuesta

13

Se las arregló para resolverlo. Se olvidó de que los DataTriggers están diseñados para Style, ControlTemplate y DataTemplate según el MSDN Docs.

La solución consistía en utilizar un EventTrigger como mensaje de error indicado. Mi solución fue la siguiente:

<EventTrigger RoutedEvent="ToggleButton.Checked"> 
    <BeginStoryboard> 
     <Storyboard> 
      <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" 
              Storyboard.TargetName="LaunchButtons"> 
       <DiscreteObjectKeyFrame KeyTime="0:0:0" 
             Value="{x:Static Visibility.Visible}" /> 
      </ObjectAnimationUsingKeyFrames> 
     </Storyboard> 
    </BeginStoryboard> 
</EventTrigger> 
<EventTrigger RoutedEvent="ToggleButton.Unchecked"> 
    <BeginStoryboard> 
     <Storyboard> 
      <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" 
              Storyboard.TargetName="LaunchButtons"> 
       <DiscreteObjectKeyFrame KeyTime="0:0:0" 
             Value="{x:Static Visibility.Collapsed}" /> 
      </ObjectAnimationUsingKeyFrames> 
     </Storyboard> 
    </BeginStoryboard> 
</EventTrigger> 

Yendo a mantener a raya el marcado esto como la respuesta en caso de que alguien más tiene otra solución.

4

También podría enlazar la Visibilidad en su panel de distribución con la propiedad IsChecked en ToggleButton. Necesitarías usar un ValueConverter personalizado. Aquí hay uno que encontré en línea:

/// <summary> 
/// WPF/Silverlight ValueConverter : Convert boolean to XAML Visibility 
/// </summary> 
[ValueConversion(typeof(bool), typeof(Visibility))] 
public class VisibilityConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
    return (value != null && (bool)value) ? Visibility.Visible : Visibility.Collapsed; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
    Visibility visibility = (Visibility)value; 
    return (visibility == Visibility.Visible); 
    } 
} 
4

Esto puede ser irremediablemente obsoleto, pero el siguiente funciona para mí. Podría ayudar a la gente corriendo en el problema: "disparadores miembros de la colección deben ser del tipo EventTrigger"

<Control> 
    <Control.Template> 
    <ControlTemplate > 

     <!-- Design --> 
     <StackPanel> 
     <CheckBox Name="CollapseControl" Content="Show" IsChecked="False" /> 
     <Label Name="CollapseTarget" Content="MyContent" Visibility="Collapsed" /> 
     </StackPanel> 

     <!-- Triggers --> 
     <ControlTemplate.Triggers > 
     <Trigger SourceName="CollapseControl" Property="IsChecked" Value="True" > 
      <Setter TargetName="CollapseTarget" Property="Visibility" Value="Visible" /> 
     </Trigger> 
     </ControlTemplate.Triggers> 

    </ControlTemplate> 
    </Control.Template> 
</Control> 

La encapsulación de "lo que se quiere controlar" dentro de un objeto de control le permite utilizar el Control.Template utilizar cualquier desencadenar lo que quieras. De esta forma, puede usar disparadores (de datos) directamente en su XAML donde lo desee sin definir un estilo estático o un UserControl completamente nuevo.

25

De MSDN Docs, según la respuesta (un poco parafraseado) de Richard C. McGuire:

DataTriggers can be used with XML tags Style, ControlTemplate and DataTemplate

Por ejemplo, si intenta agregar un disparador para un TextBlock, generará este error:

Error: Triggers collection members must be of type EventTrigger

¿Por qué? Un Trigger solo se puede colocar dentro de un Style, ControlTemplate o DataTemplate, y estamos tratando de ubicarlo directamente dentro de un TextBlock.

En este caso, la solución es fácil: simplemente ajuste el gatillo en un estilo, luego coloque este estilo dentro del TextBlock, y el error desaparecerá.

Aquí está el error de generación de XAML antes la revisión:

<TextBlock x:Name="Hello" Text="{Binding Hello, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"> 
    <TextBlock.Triggers> 
     <DataTrigger Binding="{Binding Hello}" Value="GoGreen"> 
      <Setter Property="Foreground" Value="Green" /> 
     </DataTrigger> 
    </TextBlock.Triggers> 
</TextBlock> 

Aquí está el XAML después la revisión:

<TextBlock x:Name="Hello" Text="{Binding Hello, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"> 
    <TextBlock.Style> 
     <Style TargetType="TextBlock"> 
      <Setter Property="Foreground" Value="Red" /> 
      <Style.Triggers> 
       <DataTrigger Binding="{Binding Hello}" Value="GoGreen"> 
        <Setter Property="Foreground" Value="Green" /> 
       </DataTrigger> 
      </Style.Triggers> 
     </Style> 
    </TextBlock.Style> 
</TextBlock> 

Aquí es una captura de pantalla de ejemplo que muestra que si ingrese GoGreen, el texto se vuelve verde:

enter image description here

... y si entramos en otra cosa, los valores por defecto de texto a rojo:

enter image description here

Hay un montón de material de forma gratuita en la web acerca de WPF se dispara, y todos ellos hacen un razonable buen trabajo de explicar el concepto, y this page was the one that made the penny drop for me.

+6

Si ya tiene un recurso * Style * configurado en su control de IU (como me sucedió a mí), para evitar más errores, simplemente conviértalo en la base del estilo local que tiene * DataTrigger *. Como en: '