かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

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

前回は、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に戻すだけです。