【问题标题】:Trouble using a DataTrigger with Rectangle in WPF在 WPF 中使用带矩形的 DataTrigger 时遇到问题
【发布时间】:2012-05-25 05:06:09
【问题描述】:

我是 WPF 新手,我正在尝试对矩形的大小和位置的更改进行动画处理。我通过将矩形绑定到 INotifyPropertyChanged 属性来设置它。这工作正常,但变化可能是极端的,我希望它在视觉上不那么刺耳。

这工作正常:

<Rectangle Fill="{x:Static SystemColors.ControlBrush}" 
        Stroke="black">
<Rectangle.Style>
    <Style TargetType="{x:Type Rectangle}">
        <Setter Property="Canvas.Left" Value="{Binding Path=Coil.Left, Mode=OneWay}"/>
        <Setter Property="Canvas.Top" Value="{Binding Path=Coil.Top, Mode=OneWay}"/>
        <Setter Property="Width" Value="{Binding Path=Coil.Width, Mode=OneWay}"/>
        <Setter Property="Height" Value="{Binding Path=Coil.Height, Mode=OneWay}"/>
    </Style>
</Rectangle.Style>

Coil.Left 是我的 INotifyPropertyChanged 对象中的一个 RectangleF 结构,并且包含矩形的画布的 DataContext 属性在创建对象后在我的代码中设置。

我还可以使用 EventTrigger 对其进行动画处理:

<Rectangle Fill="{x:Static SystemColors.ControlBrush}" 
        Stroke="black">
<Rectangle.Style>
    <Style TargetType="{x:Type Rectangle}">
        <Setter Property="Canvas.Left" Value="{Binding Path=Coil.Left, Mode=OneTime}"/>
        <Setter Property="Canvas.Top" Value="{Binding Path=Coil.Top, Mode=OneTime}"/>
        <Setter Property="Width" Value="{Binding Path=Coil.Width, Mode=OneTime}"/>
        <Setter Property="Height" Value="{Binding Path=Coil.Height, Mode=OneTime}"/>
    </Style>
</Rectangle.Style>
<Rectangle.Triggers>
    <EventTrigger RoutedEvent="Rectangle.MouseEnter">
        <EventTrigger.Actions>
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetProperty="Width" 
                                        To="{Binding Path=Coil.Width, Mode=OneWay}"
                                        Duration="0:0:5"/>
                    <DoubleAnimation Storyboard.TargetProperty="Height" 
                                        To="{Binding Path=Coil.Height, Mode=OneWay}"
                                        Duration="0:0:0.5"/>
                    <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" 
                                        To="{Binding Path=Coil.Left, Mode=OneWay}"
                                        Duration="0:0:5"/>
                    <DoubleAnimation Storyboard.TargetProperty="(Canvas.Top)" 
                                        To="{Binding Path=Coil.Top, Mode=OneWay}"
                                        Duration="0:0:5"/>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger.Actions>
    </EventTrigger>
</Rectangle.Triggers>

当我将鼠标移到 Rectangle 上时,它会通过动画更改为 Coil.Left、Top、Width 和 Height 的当前属性值,如预期的那样。

但是,我想要实现的是对 Coil 属性值的任何更改都是动画更改。所以我的计划是设置一个 DataTrigger 并使用一个转换器来始终返回 true,这样任何更改都会导致更改通过动画播放出来。

但无论我做什么,当我使用 DataTrigger 时,我什至在打开窗口之前都会收到异常错误,我不知道为什么会发生这种情况。为了简单起见,我取出了转换器,只使用了一个直值:

<Rectangle Fill="{x:Static SystemColors.ControlBrush}" 
        Stroke="black">
<Rectangle.Style>
    <Style TargetType="{x:Type Rectangle}">
        <Setter Property="Canvas.Left" Value="{Binding Path=Coil.Left, Mode=OneTime}"/>
        <Setter Property="Canvas.Top" Value="{Binding Path=Coil.Top, Mode=OneTime}"/>
        <Setter Property="Width" Value="{Binding Path=Coil.Width, Mode=OneTime}"/>
        <Setter Property="Height" Value="{Binding Path=Coil.Height, Mode=OneTime}"/>
    </Style>
</Rectangle.Style>
<Rectangle.Triggers>
    <DataTrigger Binding="{Binding Path=Coil.Height}" Value="60">
        <DataTrigger.EnterActions>
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetProperty="Width" 
                                        To="{Binding Path=Coil.Width, Mode=OneWay}"
                                        Duration="0:0:5"/>
                    <DoubleAnimation Storyboard.TargetProperty="Height" 
                                        To="{Binding Path=Coil.Height, Mode=OneWay}"
                                        Duration="0:0:0.5"/>
                    <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" 
                                        To="{Binding Path=Coil.Left, Mode=OneWay}"
                                        Duration="0:0:5"/>
                    <DoubleAnimation Storyboard.TargetProperty="(Canvas.Top)" 
                                        To="{Binding Path=Coil.Top, Mode=OneWay}"
                                        Duration="0:0:5"/>
                </Storyboard>
            </BeginStoryboard>
        </DataTrigger.EnterActions>
    </DataTrigger>
</Rectangle.Triggers>

关于为什么这会给我一个异常错误的任何想法?我确信这只是我对 WPF 缺乏经验的问题。这是我的第一个项目。

提前谢谢你。

--约翰

【问题讨论】:

  • 您遇到了什么异常?
  • 异常类型为 System.Windows.Markup.XamlParseException 异常内容为:'System.Windows.Shapes.Rectangle'的初始化抛出异常有{"触发器集合成员必须的内部异常属于 EventTrigger 类型。"}
  • 也许我可以用一个看起来支持 DataTriggers 的 DataTemplate 做一些事情......我的阅读还没有那么远。

标签: wpf xaml animation storyboard


【解决方案1】:

对于像Rectangle 这样的FrameworkElement,您只能使用EventTrigger。在StyleControlTemplateDataTemplate 中,您也可以使用Trigger / MultiTriggerDataTrigger / MultiDataTrigger

这意味着将您的 DataTrigger 转换为 Rectangle 样式,它应该可以工作:

<Rectangle Fill="{x:Static SystemColors.ControlBrush}" Stroke="Black">
    <Rectangle.Style>
        <Style TargetType="{x:Type Rectangle}">
            ... 
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=Coil.Height}" Value="60">
                    ...
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Rectangle.Style>
</Rectangle>

【讨论】:

  • 谢谢,但我试过了,但也遇到了异常错误:{"'Set property 'System.Windows.FrameworkElement.Style' throw an exception.'行号 '120' 和行位置 '22'。"} {"无法冻结此 Storyboard 时间线树以供跨线程使用。"}
  • 这是关于 SO 的新问题的另一个问题。
【解决方案2】:

最近正在阅读有关此内容的信息。尽管EventTriggersDataTriggers 相似,但您可以在Storyboard 中使用Binding 来表示EventTrigger,但不能使用DataTrigger

因此,如果您尝试在Storyboard 条件中使用绑定,如下所示,您将收到 System.Windows.Markup.XamlParseException 错误,

<Style.Triggers>
  <DataTrigger Binding="{Binding Path=IsBarVisible, 
    Converter={StaticResource myBooleanToVisibiltyConverter}}" Value="Visible">
    <DataTrigger.EnterActions>
      <BeginStoryboard>
        <Storyboard>
          <DoubleAnimation
            Storyboard.TargetProperty="Value"
            From="{Binding Path=ProgressedAmout}"
            To="100"
            Duration="0:0:50"
          ></DoubleAnimation>
        </Storyboard>
      </BeginStoryboard>
    </DataTrigger.EnterActions>
  </DataTrigger>
</Style.Triggers>

您可以使用和EventTrigger 作为回报或摆脱StoryboradToFrom 绑定。

【讨论】:

    猜你喜欢
    • 2011-11-03
    • 2016-06-18
    • 2017-08-05
    • 2021-09-27
    • 2020-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-20
    相关资源
    最近更新 更多