Pregunta

Estoy usando un expansor de WPF para mostrar un número de variables de proceso analógicas.

Quiero hacer de la frontera de expansión 'brillo' (o flash) cuando una de estas variables entra en una 'advertencia' o estado 'alarma'.

Para lograr esto, estoy usando algunos datos desencadena unido a un par de propiedades booleanas en mi vista del modelo ( 'AnalogWarningActive' y 'AnalogAlarmActive'). Los datos desencadena inicio a un guión gráfico que anima la opacidad frontera de expansión.

Los datos desencadena trabajo como yo esperaría: aparece el color adecuado de las fronteras y comienza la animación opacidad. Sin embargo, hay 2 problemas:

  1. La opacidad de todo el expansor (y todos contenían controles) está cambiando y no sólo de la opacidad de su frontera.

  2. Cuando las etiquetas del 'AnalogWarningActive' y 'AnalogAlarmActive' vuelven a Falso, la frontera desaparece pero la animación opactiy continúa indefinidamente (es decir. La totalidad del expansor sigue aparecen y desaparecen).

Esta es la xaml que estoy usando:

<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>
¿Fue útil?

Solución

Pregunta # 1

La configuración de un Visual como Border opacidad afecta que Visual y todos sus descendientes. Por eso Border.Opacity ajuste hace desaparecer todo.

Usted tiene dos opciones: 1. animar la propiedad Trazo frontera, o 2. Cambiar el contenido a no ser un descendiente de Frontera

.

La animación de la propiedad Stroke es trivial al código, pero tiene la desventaja de que no todos los cepillos son fácilmente animatable a transparente y la espalda. Por ejemplo, esto es difícil con los cepillos de gradiente. Además, si sus fronteras eran una variedad de colores y que no quería ir a 100% transparente no hay una buena manera de animar el accidente cerebrovascular sin cambiar el color.

Cambiar el contenido a no ser un descendiente de frontera es muy simple, y es lo que yo me inclinaría a hacer en la mayoría de los casos. Basta con sustituir:

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

con esto:

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

Ahora la opacidad del borde visible puede ser animado, mientras que el transparente controla el diseño y el recorte del niño.

Si usted no tiene ninguna CornerRadius u otro negocio divertido, sólo puede establecer un margen sobre el contenido y renunciar a la frontera transparente:

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

Pregunta # 2

A primera vista, no veo ningún problema con el XAML que causaría la animación para seguir funcionando después de que el valor de activación se remonta a falso, pero no se veía muy de cerca. De lo que he notado yo creo que sería detener la animación en el valor actual, no dejarlo encendido.

Es posible que intente reemplazar StopStoryboard con RemoveStoryboard. RemoveStoryboard debe restablecer las propiedades de animación de nuevo a sus valores originales.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top