2009-05-07 18 views
19

ho creato un controllo utente, simile al seguente:Trigger membri di raccolta devono essere di 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> 

Ho cercato di usare un DataTrigger per fare il 'lancio' StackPanel diventano visibili quando il ToggleButton è selezionato e rimane collassato in altro modo. Tuttavia, durante il runtime viene visualizzato un messaggio di errore "Inizializzazione oggetto non riuscita (ISupportInitialize.EndInit). I membri della raccolta Trigger devono essere di tipo EventTrigger". Ho provato ad aggiungerlo alla raccolta trigger di UserControl e StackPanel senza successo. Il mio trigger XAML è simile al seguente:

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

risposta

13

Gestito per capirlo. Hai dimenticato che i DataTrigger sono pensati per Style, ControlTemplate e DataTemplate per lo MSDN Docs.

Soluzione era utilizzare un EventTrigger come il messaggio di errore indicato. La mia soluzione è stata la seguente:

<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> 

Andando a tenere a bada la marcatura questa come la risposta in caso qualcuno altro ha un'altra soluzione.

4

È inoltre possibile associare la Visibilità nello stackpanel alla proprietà IsChecked in ToggleButton. Dovresti utilizzare un ValueConverter personalizzato. Eccone uno che ho trovato online:

/// <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

Questo può essere irrimediabilmente superato, ma il seguente funziona per me. Potrebbe aiutare le persone in esecuzione nel problema con: "Trigger membri di raccolta devono essere di 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> 

incapsulante "ciò che si desidera controllare" all'interno di un oggetto di controllo consente di utilizzare il Control.Template di utilizzare qualsiasi innesco che vuoi In questo modo puoi utilizzare i trigger (dati) direttamente nel tuo XAML dove vuoi senza definire uno stile statico o un UserControl completamente nuovo.

25

Da MSDN Docs, come per la risposta (un po 'parafrasato) da Richard C. McGuire:

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

Per esempio, se si tenta di aggiungere un trigger per un TextBlock, genererà questo errore:

Error: Triggers collection members must be of type EventTrigger

Perché? Un Trigger può essere inserito solo in un Style, ControlTemplate o DataTemplate e stiamo tentando di posizionarlo direttamente all'interno di un TextBlock.

In questo caso, la correzione è semplice: basta inserire il trigger in uno stile, quindi inserire questo stile all'interno dello TextBlock e l'errore scompare.

Qui è l'errore di generazione XAML prima la correzione:

<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> 

Ecco l'XAML dopo la correzione:

<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> 

Ecco un esempio screenshot che mostra che se noi immettere GoGreen, il testo diventa verde:

enter image description here

... e se entriamo qualcosa d'altro, il testo di default al rosso:

enter image description here

C'è un sacco di materiale gratuito sul web su WPF innesca, e tutti loro fare un ragionevolmente buon lavoro di spiegare il concetto e this page was the one that made the penny drop for me.

+6

Se si dispone già di una risorsa * di stile * sul controllo dell'interfaccia utente (come è successo a me), per evitare ulteriori errori, basta trasformarlo nella base dello stile locale con * DataTrigger *. Come in: