Элементы коллекции триггеров должны быть типа 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>
Ответы
Ответ 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.