.net 触发器集合成员必须是 EventTrigger 类型

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/836703/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 12:39:15  来源:igfitidea点击:

Triggers collection members must be of type EventTrigger

.netwpfdatatrigger

提问by Richard McGuire

I've created a UserControl, similar to the following:

我创建了一个 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>

I've been trying to use a DataTrigger to make the 'Launch' StackPanel become visible when the ToggleButton is checked, and remain collapsed otherwise. However, at runtime I get an error stating "Failed object initialization (ISupportInitialize.EndInit). Triggers collection members must be of type EventTrigger". I've tried adding it to the trigger collection of the UserControl and StackPanel with no success. My trigger XAML looks like the following:

我一直在尝试使用 DataTrigger 在选中 ToggleButton 时使“Launch”StackPanel 变得可见,否则保持折叠状态。但是,在运行时,我收到一条错误消息,指出“对象初始化失败 (ISupportInitialize.EndInit)。触发器集合成员必须是 EventTrigger 类型”。我尝试将它添加到 UserControl 和 StackPanel 的触发器集合中,但没有成功。我的触发器 XAML 如下所示:

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

采纳答案by Richard McGuire

Managed to figure it out. Forgot that DataTriggers are meant for Style, ControlTemplate and DataTemplate per the MSDN Docs.

设法弄明白了。忘记了根据MSDN 文档,DataTriggers 是用于 Style、ControlTemplate 和 DataTemplate 的

Solution was to use an EventTrigger as the error message indicated. My solution was the following:

解决方案是使用 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>

Going to hold off marking this as the answer in case someone else has another solution.

将推迟将此标记为答案,以防其他人有其他解决方案。

回答by Contango

From MSDN Docs, as per the (slightly paraphrased) answer from Richard C. McGuire:

来自MSDN Docs,根据 Richard C. McGuire 的(稍微解释一下)回答:

DataTriggers can be used with XML tags Style, ControlTemplateand DataTemplate

DataTriggers 可以与 XML 标签StyleControlTemplateDataTemplate 一起使用

For example, if you attempt to add a trigger to a TextBlock, it will generate this error:

例如,如果您尝试向 a 添加触发器TextBlock,则会生成以下错误:

Error: Triggers collection members must be of type EventTrigger

错误:触发器集合成员必须是 EventTrigger 类型

Why? A Triggercan only be placed inside a Style, ControlTemplateor DataTemplate, and we are trying to place it directly inside a TextBlock.

为什么?ATrigger只能放在 a Style, ControlTemplateor 中DataTemplate,而我们正试图将它直接放在 a 中TextBlock

In this case, the fix is easy: just wrap the trigger in a style, then place this style inside the TextBlock, and the error will disappear.

在这种情况下,修复很简单:只需将触发器包裹在一个 style 中,然后将该 style 放在 中TextBlock,错误就会消失。

Here is the error-generating XAML beforethe fix:

这是修复的错误生成 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>

Here is the XAML afterthe fix:

这是修复的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>

Here is a sample screenshot showing that if we enter GoGreen, the text goes green:

这是一个示例屏幕截图,显示如果我们输入GoGreen,文本会变为绿色:

enter image description here

在此处输入图片说明

... and if we enter something else, the text defaults to red:

...如果我们输入其他内容,文本默认为红色:

enter image description here

在此处输入图片说明

There is loads of free material on the web about WPF triggers, and all of them do a reasonably good job of explaining the concept, and this page was the one that made the penny drop for me.

网络上有大量关于 WPF 触发器的免费材料,它们都很好地解释了这个概念,而这个页面是让我大吃一惊的页面

回答by mdm20

You could also bind the Visibility in your stackpanel to the IsChecked property in the ToggleButton. You would need to use a custom ValueConverter. Here is one I found online:

您还可以将堆栈面板中的 Visibility 绑定到 ToggleButton 中的 IsChecked 属性。您需要使用自定义 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);
  }
}

回答by Marko

This may be hopelessly outdated, but the following works for me. It might help people running into the problem with: "Triggers collection members must be of type EventTrigger"

这可能已经过时了,但以下内容对我有用。它可能会帮助人们遇到以下问题:“触发器集合成员必须是 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>

Encapsulating "what you want to control" inside a Control object allows you to use the Control.Template to use any trigger you want. This way you can use (data)triggers directly in your XAML where you want to without defining a static style or a completely new UserControl.

在 Control 对象中封装“您想要控制的内容”允许您使用 Control.Template 来使用您想要的任何触发器。通过这种方式,您可以直接在 XAML 中使用(数据)触发器,而无需定义静态样式或全新的 UserControl。