Как сделать моргание эллипса? - PullRequest
5 голосов
/ 22 сентября 2009

Я пытаюсь сделать пользовательский элемент управления в WPF. Я хочу, чтобы он имитировал поведение светодиода, который может мигать.

Элемент управления имеет три состояния: Вкл., Выкл. И Мигает.

Я знаю, как включить и выключить код, но этот WPF-анимация просто сводит меня с ума !!!! Я ничего не могу оживить. План состоит в том, чтобы иметь собственность, названную государством. Когда пользователь устанавливает значение для мигания, я хочу, чтобы элемент управления чередовался между зеленым и серым. Я предполагаю, что мне нужно свойство зависимости здесь, но понятия не имею. У меня было больше xaml раньше, но я просто стер все это. кажется, ничего не делает. Я бы хотел сделать это наилучшим из возможных способов, но сейчас я возьму все, что угодно. Сейчас я наполовину написал нить, которая меняет цвет вручную.

<UserControl x:Class="WpfAnimation.LED"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="300">

<Grid>
    <Ellipse x:Name="MyLight" Height="Auto" Width="Auto"/>
</Grid>

</UserControl>

Ответы [ 2 ]

8 голосов
/ 22 сентября 2009

Вы можете сделать это с анимацией, которая автоматически переворачивает и повторяет (это для Silverlight):

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="Blinker.MainPage"
    Width="640" Height="480" Loaded="UserControl_Loaded">
    <UserControl.Resources>
        <Storyboard x:Name="Blink" AutoReverse="True" RepeatBehavior="Forever">
            <ColorAnimationUsingKeyFrames BeginTime="00:00:00"
              Storyboard.TargetName="ellipse"
              Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
                 <EasingColorKeyFrame KeyTime="00:00:01" Value="Gray"/>
            </ColorAnimationUsingKeyFrames>
         </Storyboard>
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot" Background="White">
         <Ellipse x:Name="ellipse" Fill="Green" Stroke="Black"/>
    </Grid>
</UserControl>

и затем запускайте анимацию при загрузке элемента управления или при установке свойства - вам не нужно свойство зависимости, если вы не

private bool blinking;
public bool IsBlinking
{
    get
    {
       return blinking;
    }
    set
    {
        if (value)
        {
             this.Blink.Begin();
        }
        else
        {
             this.Blink.Stop();
        }

        this.blinking = value;
    }
}

или при запуске:

private void UserControl_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
    this.Blink.Begin();
}

Вот еще один способ сделать это в WPF - с помощью VisualStateManager - который также будет работать в Silverlight:

<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="BlinkerApp.Blinker"
x:Name="UserControl"
d:DesignWidth="100" d:DesignHeight="100">
<Grid x:Name="LayoutRoot">
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="BlinkStates">
            <VisualState x:Name="Blinking">
                <Storyboard AutoReverse="True" RepeatBehavior="Forever">
                    <ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="ellipse" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
                        <SplineColorKeyFrame KeyTime="00:00:01" Value="Gray"/>
                    </ColorAnimationUsingKeyFrames>
                </Storyboard>
            </VisualState>
            <VisualState x:Name="Stopped"/>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    <Ellipse x:Name="ellipse" Fill="Green" Stroke="Black"/>
</Grid>

и затем свойство IsBlinking переключает визуальное состояние:

namespace BlinkerApp
{
    using System.Windows;
    using System.Windows.Controls;

/// <summary>
/// Interaction logic for Blinker.xaml
/// </summary>
public partial class Blinker : UserControl
{
    private bool blinking;

    public Blinker()
    {
        this.InitializeComponent();
    }

    public bool IsBlinking
    {    
        get    
        {       
            return blinking;    
        }    

        set    
        {        
            if (value)        
            {
                VisualStateManager.GoToState(this, "Blinking", true);
            }        
            else        
            {
                VisualStateManager.GoToState(this, "Stopped", true);
            }        

            this.blinking = value;    
        }
    }       
}
}
4 голосов
/ 25 сентября 2009

Чтобы обеспечить больший контроль над частотой мигания и тому подобным в вашем коде, я бы предложил иметь перенаправленное событие в вашем UserControl под названием Blink:

public static readonly RoutedEvent BlinkEvent = EventManager.RegisterRoutedEvent("Blink", RoutingStrategy.Direct, typeof(RoutedEventHandler), typeof(LedControl));
public event RoutedEventHandler Blink
{
    add { AddHandler(BlinkEvent, value); }
    remove { RemoveHandler(BlinkEvent, value); }
}

В своем коде вы можете установить таймер для поднятия события так часто, как вам нравится (это также дает вам возможность мигать один раз, когда вы хотите:

RaiseEvent(new RoutedEventArgs(LedControl.Blink));

Теперь в XAML следующий код сделает видимым свечение и установит для свойства fill вашего эллипса (ledEllipse) ярко-зеленый радиальный градиент, а затем вернет значение заливки тусклому «неосвещенному» зеленому (что вы могли бы сделать). изменить на серый, если хотите). Вы можете просто изменить продолжительность, чтобы мигание длилось дольше.

<UserControl.Triggers>
    <EventTrigger RoutedEvent="local:LedControl.Blink">
        <EventTrigger.Actions>
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetName="glow"
                                     Storyboard.TargetProperty="Opacity"
                                     To="100"
                                     AutoReverse="True"
                                     Duration="0:0:0.075" />
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ledEllipse"
                                                  Storyboard.TargetProperty="Fill"
                                                  Duration="0:0:0.15">
                        <ObjectAnimationUsingKeyFrames.KeyFrames>
                            <DiscreteObjectKeyFrame KeyTime="0:0:0.01">
                                <DiscreteObjectKeyFrame.Value>
                                    <RadialGradientBrush>
                                        <!--bright Green Brush-->
                                        <GradientStop Color="#FF215416" Offset="1"/>
                                        <GradientStop Color="#FE38DA2E" Offset="0"/>
                                        <GradientStop Color="#FE81FF79" Offset="0.688"/>
                                    </RadialGradientBrush>
                                </DiscreteObjectKeyFrame.Value>
                            </DiscreteObjectKeyFrame>
                            <DiscreteObjectKeyFrame KeyTime="0:0:0.15" >
                                <DiscreteObjectKeyFrame.Value>
                                    <RadialGradientBrush>
                                        <!--dim Green Brush-->
                                        <GradientStop Color="#FF21471A" Offset="1"/>
                                        <GradientStop Color="#FF33802F" Offset="0"/>
                                        <GradientStop Color="#FF35932F" Offset="0.688"/>
                                    </RadialGradientBrush>
                                </DiscreteObjectKeyFrame.Value>
                            </DiscreteObjectKeyFrame>
                        </ObjectAnimationUsingKeyFrames.KeyFrames>
                    </ObjectAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger.Actions>
    </EventTrigger>
</UserControl.Triggers>

Кроме того, я непосредственно ссылаюсь на эллипс 'ledEllipse' и соответствующий ему DropShadowEffect 'glow', которые определены в ledControl следующим образом (redLight - это просто еще одна кисть радиального градиента, с которой я запускаю свойство fill моего светодиода):

<Ellipse x:Name="statusLight" Height="16" Width="16" Margin="0" Fill="{DynamicResource redLight}" >
    <Ellipse.Effect>
        <DropShadowEffect x:Name="glow" ShadowDepth="0" Color="Lime" BlurRadius="10" Opacity="0" />
    </Ellipse.Effect>
</Ellipse>

Примечание. DropShadowEffect появился в .Net 3.5, но вы можете удалить его, если не хотите использовать эффект свечения (но он хорошо выглядит на однотонном контрастном фоне).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...