かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

ボタンのダブルクリックを抑止したい

前回は、ControlTemplateで頑張りましたが、今回はBehaviorにしてみました。個人的には、こっちのほうが好きですね。Behaviorの設置忘れがあったときにチェックするのがめんどくさそうですが…。

using Microsoft.Xaml.Interactivity;
using System;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls.Primitives;

namespace BasicTemplate1
{
    /// <summary>
    /// ボタン連打防止ビヘイビア
    /// </summary>
    [TypeConstraint(typeof(ButtonBase))]
    public class RendaStopBehavior : DependencyObject, IBehavior
    {
        public DependencyObject AssociatedObject { get; private set; }

        private ButtonBase TargetObject { get; set; }

        /// <summary>
        /// ボタンを押してから無効になっている時間(ms)を取得または設定します
        /// </summary>
        public int DisableSpan { get; set; }

        public RendaStopBehavior()
        {
            this.DisableSpan = 1000;
        }

        public void Attach(DependencyObject associatedObject)
        {
            this.AssociatedObject = associatedObject;
            this.TargetObject = this.AssociatedObject as ButtonBase;
            if (this.TargetObject == null)
            {
                throw new InvalidOperationException();
            }

            this.TargetObject.Click += this.TargetObject_Click;
        }

        private async void TargetObject_Click(object sender, RoutedEventArgs e)
        {
            // クリックされたら一定時間無効化する
            this.TargetObject.IsEnabled = false;
            await Task.Delay(this.DisableSpan);
            this.TargetObject.IsEnabled = true;
        }

        public void Detach()
        {
            this.TargetObject.Click -= this.TargetObject_Click;
        }
    }
}

コードは簡単。クリックされたらIsEnabledをfalseにしてTask.Delayで指定された時間待機してIsEnabledをtrueに戻すだけです。