1

我正在使用 WPF 扩展器来显示许多模拟过程变量。

当这些变量之一进入“警告”或“警报”状态时,我想让扩展器的边框“发光”(或闪烁)。

为了实现这一点,我在我的视图模型中使用了一些绑定到几个布尔属性的数据触发器(“AnalogWarningActive”和“AnalogAlarmActive”)。数据触发器启动了一个故事板,该故事板为扩展器边框不透明度设置了动画。

数据触发器按我的预期工作:出现正确的边框颜色并且不透明动画开始。但是,有两个问题:

  1. 整个扩展器(以及所有包含的控件)的不透明度正在发生变化,而不仅仅是其边框的不透明度。

  2. 当 'AnalogWarningActive' 和 'AnalogAlarmActive' 标签返回 False 时,边框会消失,但不透明动画会无限期地继续(即整个扩展器继续淡入淡出)。

这是我正在使用的 xaml:

<SolidColorBrush x:Key="AnalogAlarmBrush" Color="#FFFF8080" />
<SolidColorBrush x:Key="AnalogWarningBrush" Color="#FFFFFF80" />

<Storyboard x:Key="AlarmBorderFlasher" AutoReverse="True" RepeatBehavior="Forever">
    <DoubleAnimation  
        Storyboard.TargetProperty="(Border.Opacity)" 
        From="1.0" To="0.4" 
        Duration="0:0:0.8" />
</Storyboard>

<Expander Header="Test Data" IsExpanded="True">
    <Expander.Style>
        <Style TargetType="{x:Type Expander}">
            <Style.Triggers>

                <DataTrigger Binding="{Binding Path=AnalogWarningActive}" Value="True" >

                    <DataTrigger.EnterActions>
                        <BeginStoryboard Name="WarningBorderStoryboard" Storyboard="{StaticResource AlarmBorderFlasher}" />
                    </DataTrigger.EnterActions>
                    <DataTrigger.ExitActions>
                        <StopStoryboard BeginStoryboardName="WarningBorderStoryboard" />
                    </DataTrigger.ExitActions>

                    <DataTrigger.Setters>
                        <Setter Property="BorderBrush" Value="{StaticResource AnalogWarningBrush}" />
                        <Setter Property="BorderThickness" Value="4" />
                    </DataTrigger.Setters>

                </DataTrigger>

                <DataTrigger Binding="{Binding Path=AnalogAlarmActive}" Value="True" >

                    <DataTrigger.EnterActions>
                        <BeginStoryboard Name="AlarmBorderStoryboard" Storyboard="{StaticResource AlarmBorderFlasher}" />
                    </DataTrigger.EnterActions>
                    <DataTrigger.ExitActions>
                        <StopStoryboard BeginStoryboardName="AlarmBorderStoryboard" />
                    </DataTrigger.ExitActions>

                    <DataTrigger.Setters>
                        <Setter Property="BorderBrush" Value="{StaticResource AnalogAlarmBrush}" />
                        <Setter Property="BorderThickness" Value="4" />
                    </DataTrigger.Setters>

                </DataTrigger>

            </Style.Triggers>
        </Style>
    </Expander.Style>

    <!-- snipped the contents of the expander (a tabcontrol and a few text boxes, labels, etc)-->

</Expander>
4

1 回答 1

1

问题 #1

视觉对象(例如边框)上的不透明度设置会影响该视觉对象及其所有后代。这就是为什么设置 Border.Opacity 会使一切消失。

您有两个选择:1. 为边框 Stroke 属性设置动画,或者 2. 将内容更改为不是 Border 的后代。

为 Stroke 属性设置动画对于代码来说是微不足道的,但缺点是并非所有画笔都可以轻松地设置为透明和背面的动画。例如,渐变画笔很难做到这一点。此外,如果您的边框有多种颜色,并且您不想达到 100% 透明,则没有好的方法可以在不更改颜色的情况下为 Stroke 设置动画。

将内容更改为不是 Border 的后代非常简单,并且在大多数情况下我会倾向于这样做。只需更换:

<Border x:Name="MyBorder" Stroke="Red" StrokeThickness="3" CornerRadius="6">
  <my:ContentHere />
</Border>

有了这个:

<Grid>
  <Border x:Name="MyBorder" Stroke="Red" StrokeThickness="3" Stroke="Red" CornerRadius="6">
  <Border Stroke="Transparent" StrokeThickness="3" CornerRadius="Red">
    <my:ContentHere />
  </Border>
</Grid>

现在可见边框的不透明度可以设置动画,而透明边框控制子元素的布局和剪辑。

如果你没有任何 CornerRadius 或其他有趣的业务,你可以在内容上设置一个边距并放弃透明边框:

<Grid>
  <Border x:Name="MyBorder" Stroke="Red" StrokeThickness="3" />
  <my:ContentHere Margin="3" />
</Grid>

问题2

乍一看,我没有看到您的 XAML 有任何问题会导致动画在触发值返回 false 后继续运行,但我没有仔细观察。从我注意到的情况来看,我认为它会以当前值停止动画,而不是让它继续运行。

您可以尝试将 StopStoryboard 替换为 RemoveStoryboard。RemoveStoryboard 应该将动画属性重置为其原始值。

于 2009-11-09T19:28:03.560 回答