Подтвердить что ты не робот

Элементы коллекции триггеров должны быть типа 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 "Launch" стал видимым, когда отмечен 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>
4b9b3361

Ответ 1

Удалось выяснить. Забыл, что 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>

Продолжаем удерживать отметку этого как ответ, если у кого-то другое решение.

Ответ 2

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

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

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

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

Почему? A 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, текст станет зеленым:

enter image description here

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

enter image description here

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

Ответ 3

Вы также можете привязать видимость в вашей панели стека к свойству 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);
  }
}

Ответ 4

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