i++

プログラム系のメモ書きなど

WPF/XAML : Behavior の PastingHandler で MessageBox を表示する

ポイント

  • PastingHandler をつけるには DataObject.AddPastingHandler を使用する
    • 外すときは RemovePastingHandler
  • PastingHandler として設定した関数で直接 MessageBox.Show を呼ぶと例外が発生するので Dispatcher.InvokeAsync を使う
    • Aync じゃない方の Invoke でも例外発生

サンプルコード

数字以外の入力を禁止する、という、TextBox 用の Behavior です。

using System.Windows.Interactivity;
using System.Windows.Controls;
using System.Windows;

class NumberBehavior : Behavior<TextBox>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.PreviewTextInput += AssociatedObject_PreviewTextInput;
        DataObject.AddPastingHandler(AssociatedObject, AssociatedObject_PastingHandler);
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        AssociatedObject.PreviewTextInput -= AssociatedObject_PreviewTextInput;
        DataObject.RemovePastingHandler(AssociatedObject, AssociatedObject_PastingHandler);
    }

    private bool IsAllNumber(string text)
    {
        return !text.Any(c => !char.IsNumber(c));
    }

    private void AssociatedObject_PreviewTextInput(object sender, System.Windows.Input.TextCompositionEventArgs e)
    {
        // e.Handled = true を返すとこれ以降のイベントが発生しなくなる
        // => テキストボックスへの入力が行われない
        if(!IsAllNumber(e.Text))
        {
            e.Handled = true;
        }
    }

    private void AssociatedObject_PastingHandler(object sender, DataObjectPastingEventArgs e)
    {
        if(e.DataObject.GetDataPresent(DataFormats.Text))
        {
            string text = Convert.ToString(e.DataObject.GetData(DataFormats.Text));
            if(!IsAllNumber(text))
            {
                Dispatcher.InvokeAsync(() =>
                {
                    MessageBox.Show("数字以外の文字を含むテキストはペーストできません");
                });
                e.CancelCommand();
            }
        }
        else
        {
            MessageBox.Show("ペーストできる有効なデータがコピーされていません");
            e.CancelCommand();
        }
    }
}

参考