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

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

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

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

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

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

这是我正在使用的 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>
有帮助吗?

解决方案

问题#1

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

你有两个选择:1.对边框 Stroke 属性进行动画处理,或 2。将内容更改为不是 Border 的后代。

对 Stroke 属性进行动画处理对于代码来说很简单,但缺点是并非所有画笔都可以轻松设置为透明和返回动画。例如,使用渐变画笔就很难做到这一点。另外,如果您的边框有多种颜色,并且您不想达到 100% 透明,则没有什么好方法可以在不更改颜色的情况下为描边设置动画。

将内容更改为不是 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 后继续运行,但我没有仔细观察。根据我的观察,我认为它会将动画停止在当前值,而不是让它继续运行。

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top