Domanda

Io sto usando un WPF Expander per visualizzare una serie di variabili di processo analogici.

Voglio fare del expander confine 'bagliore' (o flash), quando una di queste variabili entra in un 'avvertimento' o lo stato 'allarme'.

Per raggiungere questo obiettivo, sto utilizzando alcuni dati innesca legato a un paio di proprietà booleane, a mio avviso il modello ( 'AnalogWarningActive' e 'AnalogAlarmActive'). I dati innesca dare il via uno storyboard che anima l'opacità expander confine.

I dati innesca lavoro come mi aspetto: compare il colore del bordo corretta e l'animazione di opacità inizia. Tuttavia, ci sono 2 problemi:

  1. L'opacità dell'intero espansore (e tutti i controlli contenuti) sta cambiando e non solo l'opacità del suo bordo.

  2. Quando i tag del 'AnalogWarningActive' e 'AnalogAlarmActive' tornano a False, la frontiera scompare, ma l'animazione opactiy continua indefinitamente (es. L'intera espansione continua a svanire in e out).

Ecco l'XAML che sto 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>
È stato utile?

Soluzione

Domanda # 1

L'impostazione su un Visual quali opacità Border influenza che Visual e tutti i suoi discendenti. Ecco perché l'impostazione Border.Opacity rende tutto scomparire.

Hai due scelte: 1. animare la proprietà di tratto di confine, o 2. modificare il contenuto di non essere un discendente di Border

.

Animare la proprietà Stroke è banale codice, ma ha lo svantaggio che non tutte le spazzole sono facilmente animatable a trasparente e indietro. Per esempio, questo è difficile con spazzole gradiente. Inoltre, se i tuoi confini sono stati una varietà di colori e non si volevano andare al 100% trasparente non c'è buon modo per animare la corsa senza cambiare il colore.

La modifica del contenuto di non essere un discendente di Border è molto semplice, ed è quello che vorrei essere incline a fare nella maggior parte dei casi. Basta sostituire:

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

con questo:

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

Ora l'opacità del bordo visibile può essere animata, mentre quello trasparente controlla il layout e ritaglio del bambino.

Se non si dispone di alcun CornerRadius o altre attività divertenti, si può semplicemente impostare un margine sul contenuto e rinunciare al confine trasparente:

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

Domanda # 2

A prima vista non vedo alcun problema con il vostro XAML che causerebbe l'animazione per mantenere in esecuzione dopo il valore di innesco risale al falso, ma non ho guardato molto da vicino. Da quello che ho notato io penso che sarebbe interrompere l'animazione al valore corrente, non lasciarlo in esecuzione.

Si potrebbe provare a sostituire StopStoryboard con RemoveStoryboard. RemoveStoryboard dovrebbe reimpostare le proprietà animate di nuovo ai loro valori originali.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top