0

ユーザーが自分のフォームで違法なアクションを実行しようとしたときに、警告システムを実装しようとしています。アイデアは、メソッドを呼び出しStatusBarFade、書き込む必要があるパラメーターを指定して、そのメソッドにテキストを表示させ、1 秒半色を変更して点滅させ、さらに 1 秒半静止させ、その後テキストを表示することです。消えるだろう。

点滅は1回おきに機能しますが、テキストは通常​​どおり消えます。

私はこのコードが非常に厄介であり、それを行うためのより良い方法があることを知っていますが、デリゲートがどのように機能するかを正確に知らないため、それらを適切に利用する方法がわかりません. うまくいけば、誰かが私が間違っていることを説明できるでしょう。とにかく、いくつかのテストの後、2 つのタイマーを用意するのが最善であることに気付きました。問題は、このコードが 1 回おきに機能することです。

    private Timer timer = new System.Timers.Timer();
    private Timer timerColor = new System.Timers.Timer();
    private void StatusBarFade(string ispis)
    {
        statusBar1AS2.Content = ispis;
        int i = 0;
        timerColor.Interval = 100;
        timerColor.AutoReset = true;
        timerColor.Elapsed += delegate(object sender, System.Timers.ElapsedEventArgs e)
        {
            this.Dispatcher.BeginInvoke(new Action(() =>
                {
                    ++i;
                    if (statusBar1AS2.Foreground == Brushes.Black)
                        statusBar1AS2.Foreground = Brushes.Gold;
                    else
                        statusBar1AS2.Foreground = Brushes.Black;
                    if (i > 15)
                    {
                        statusBar1AS2.Foreground = Brushes.Black;
                        i = 0;
                        timerColor.Stop();
                    }
                }));
        };
        timerColor.Start();

        timer.Interval = 3000;
        timer.Elapsed += delegate(object sender, System.Timers.ElapsedEventArgs e)
        {
            timer.Stop();
            this.Dispatcher.BeginInvoke(new Action(() => { statusBar1AS2.Content = ""; }));
        };
        timer.Start();
    }

私がデリゲートを理解している限り、テキストが変更されるたびに同じデリゲートを timer.Elapsed イベントに追加するのではなく、たとえばコンストラクターで一度だけ追加する必要があります。問題は、コードで行った方法でカウンターを使用する方法がわからないことiです。

4

3 に答える 3

4

次のアニメーションを簡単に使用できます。

var animation = new ColorAnimation
{
    From = Colors.Black,
    To = Colors.Gold,
    AutoReverse = true,
    Duration = TimeSpan.FromSeconds(0.1),
    RepeatBehavior = new RepeatBehavior(TimeSpan.FromSeconds(1.5))
};

animation.Completed += (o, e) => statusBar.Content = string.Empty;

statusBar.Foreground = new SolidColorBrush();
statusBar.Foreground.BeginAnimation(SolidColorBrush.ColorProperty, animation);

更新: メッセージの削除を遅らせるために、もちろんタイマーを使用できます。DispatcherTimerを使用して、以下に示すように StatusBarFade メソッドを記述することができます。

private void StatusBarFade(string message)
{
    statusBar.Content = message;

    var animation = new ColorAnimation
    {
        From = Colors.Gold,
        To = Colors.Black,
        AutoReverse = true,
        Duration = TimeSpan.FromSeconds(0.1),
        RepeatBehavior = new RepeatBehavior(TimeSpan.FromSeconds(1.5)),
    };

    statusBar.Foreground = new SolidColorBrush();
    statusBar.Foreground.BeginAnimation(SolidColorBrush.ColorProperty, animation);

    var timer = new DispatcherTimer
    {
        Interval = TimeSpan.FromSeconds(4.5)
    };

    timer.Tick +=
        (o, e) =>
        {
            timer.Stop();
            statusBar.Content = string.Empty;
        };

    timer.Start();
}
于 2013-05-29T14:19:04.550 に答える
0

@クレメンスの答えは、あなたが探しているものです。この行動の理由を知りたかっただけです。

あなたが経験している問題は、タイマーの反復が完了するとデリゲートを削除せずにアタッチするという事実によるものです。

したがって、偶数の発生ごとにこの動作が見られるのは、その時点で偶数のデリゲートがタイマーの経過イベントに関連付けられているため、2、4、6 の増分でかなり増加するためです...したがって、黒から終了します- > ブラックとゴールドへの切り替えはありません。アニメーションの全体的な時間も、同じように段階的に減少します。それが問題でした。

そのための修正は次のようになります(これを使用しないでください。ケースとして見てください。@Clemensアプローチを使用するか、ストーリーボードをxamlで直接使用してください)

private int i = 0;

private void StatusBarFade(string ispis) {
  i = 0;
  statusBar1AS2.Content = ispis;
  timerColor.Interval = 100;
  timerColor.AutoReset = true;
  timerColor.Elapsed += TimerColorOnElapsed;
  timerColor.Start();
}

private void TimerColorOnElapsed(object sender, ElapsedEventArgs elapsedEventArgs) {
  Dispatcher.BeginInvoke(
    (new Action(
      () => {
        ++i;
        statusBar1AS2.Foreground = i % 2 == 0 || i > 15 ? Brushes.Black : Brushes.Gold;
        if (i < 30)
          return;
        timerColor.Stop();
        timerColor.Elapsed -= TimerColorOnElapsed;
        statusBar1AS2.Content = string.Empty;
      })));
}
于 2013-05-29T14:42:38.890 に答える
0

ストーリーボードで試してください。

<Storyboard x:Key="TestBlinkStoryboard" AutoReverse="True" RepeatBehavior="Forever">
        <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="textBlock">
            <EasingColorKeyFrame KeyTime="0" Value="Black"/>
            <EasingColorKeyFrame KeyTime="0:0:0.5" Value="#FFE91414">
                <EasingColorKeyFrame.EasingFunction>
                    <BounceEase EasingMode="EaseInOut"/>
                </EasingColorKeyFrame.EasingFunction>
            </EasingColorKeyFrame>
        </ColorAnimationUsingKeyFrames>
    </Storyboard>
于 2013-05-29T14:11:55.523 に答える