32

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

4 回答 4

55

来自MSDN Docs,根据 Richard C. McGuire 的(稍微转述的)回答:

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

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

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

为什么?ATrigger只能放在 a或中Style,而我们正试图将它直接放在 a中。ControlTemplateDataTemplateTextBlock

在这种情况下,修复很简单:只需将触发器包装在 style中,然后将此样式放在 中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 触发器的免费材料,所有这些材料都很好地解释了这个概念,而这个页面让我一分钱一分货

于 2014-09-20T17:39:31.900 回答
16

设法弄清楚了。根据MSDN Docs,忘记了 DataTriggers 是为 Style、ControlTemplate 和 DataTemplate 设计的。

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

如果其他人有其他解决方案,请推迟将其标记为答案。

于 2009-05-07T20:10:33.460 回答
5

您还可以将堆栈面板中的 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) =>
        value != null && (bool)value ? Visibility.Visible : Visibility.Collapsed;
 
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) =>
        (Visibility)value == Visibility.Visible;
}
于 2009-05-07T21:06:31.530 回答
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。

于 2013-07-18T13:06:10.153 回答