Элементы коллекции триггеров должны иметь тип EventTrigger.

Я создал UserControl, подобный следующему:

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

Я пытался использовать DataTrigger, чтобы StackPanel «Запуск» стал видимым, когда установлен флажок ToggleButton, и в противном случае оставался свернутым. Однако во время выполнения я получаю сообщение об ошибке «Ошибка инициализации объекта (ISupportInitialize.EndInit). Члены коллекции триггеров должны иметь тип EventTrigger». Я безуспешно пытался добавить его в коллекцию триггеров UserControl и StackPanel. Мой триггер XAML выглядит следующим образом:

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

person Richard McGuire    schedule 07.05.2009    source источник


Ответы (4)


Из документов MSDN, согласно (слегка перефразированному) ответ от Ричарда С. Макгуайра:

DataTriggers можно использовать с тегами XML Style, ControlTemplate и DataTemplate.

Например, если вы попытаетесь добавить триггер в TextBlock, будет выдана следующая ошибка:

Ошибка: элементы коллекции триггеров должны быть типа EventTrigger

Почему? Trigger можно поместить только внутри Style, ControlTemplate или DataTemplate, а мы пытаемся разместить его непосредственно внутри TextBlock.

В этом случае исправить просто: просто оберните триггер стилем, затем поместите этот стиль внутрь TextBlock, и ошибка исчезнет.

Вот код XAML, генерирующий ошибки, до исправления:

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

Вот XAML после исправления:

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

Вот пример снимка экрана, показывающий, что если мы вводим GoGreen, текст становится зеленым:

введите здесь описание изображения

... и если мы введем что-то еще, текст по умолчанию будет красным:

введите здесь описание изображения

В Интернете есть множество бесплатных материалов о триггерах WPF, и все они достаточно хорошо объясняют концепцию, и эта страница заставила меня задуматься.

person Contango    schedule 20.09.2014
comment
Если у вас уже есть ресурс Style, установленный в элементе управления пользовательского интерфейса (как это случилось со мной), во избежание дальнейших ошибок просто превратите его в основу локального стиля, используя DataTrigger< /я>. Как в: <TextBlock.Style> <Style TargetType="TextBlock" BasedOn="{StaticResource YourPreviousStyleResource}"> <Style.Triggers> <DataTrigger ... HTH - person superjos; 11.03.2015

Удалось разобраться. Забыл, что DataTriggers предназначены для Style, ControlTemplate и DataTemplate согласно документам MSDN. .

Решение заключалось в использовании EventTrigger, как указано в сообщении об ошибке. Мое решение было следующим:

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

Собираюсь не отмечать это как ответ на случай, если у кого-то есть другое решение.

person Richard McGuire    schedule 07.05.2009

Вы также можете привязать видимость в своей панели стека к свойству IsChecked в ToggleButton. Вам нужно будет использовать пользовательский ValueConverter. Вот один, который я нашел в Интернете:

/// <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);
  }
}
person mdm20    schedule 07.05.2009

Это может быть безнадежно устаревшим, но для меня работает следующее. Это может помочь людям, столкнувшимся с проблемой: «Члены коллекции триггеров должны быть типа 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>

Инкапсуляция «того, чем вы хотите управлять» внутри объекта Control позволяет вам использовать Control.Template для использования любого триггера, который вы хотите. Таким образом, вы можете использовать триггеры (данных) непосредственно в своем XAML, где хотите, без определения статического стиля или совершенно нового пользовательского элемента управления.

person Marko    schedule 18.07.2013