locked
TextBoxで実数及び整数のみを取り込む方法を教えてください RRS feed

  • 質問

  • KeyDownイベントでKeyEventArgs.Keyをチェックしてみたのですが値がどうもおかしいよな気がします。

    例えば、

    ピリオド → UnKnown

    @    →  D2 (2もD2です)

    これでは、入力された文字が何だかわかりません。

    InputScope は Digits を使用しています。

    皆さんはどうなさっているのですか?

    • 移動 Mike Wang (MSCS) 2012年10月2日 11:15 (移動元:Windows Phone 7 向けの開発)
    2011年10月26日 10:05

回答

  • USのフォーラムなども見てみましたが、InputScope="Digits"の場合、とりあえずは

    1. Key.Unknownが来たらe.PlatformKeyCodeをチェックする
    2. ハードウェアキーなどの特殊ケースは諦める

    しかなさそうです。

    なので無理にやるなら力技ですがこんな感じでいかがでしょうか?

    private readonly Key[] numeric = new Key[] 
        {
            Key.Back, Key.D0, Key.D1, Key.D2, Key.D3, Key.D4, Key.D5,
            Key.D6, Key.D7, Key.D8, Key.D9, Key.Unknown
        };
    
    private void text1_KeyDown(object sender, KeyEventArgs e)
    {
        if (Array.IndexOf(numeric, e.Key) == -1)
        {
            if (e.Key != Key.Unknown && e.PlatformKeyCode != 190)
                e.Handled = true;
        }
    }
    
    private void text1_KeyUp(object sender, KeyEventArgs e)
    {
        var tb = sender as TextBox;
        var t1 = FilterNonNum(tb.Text.Substring(0, tb.SelectionStart));
        var t2 = FilterNonNum(tb.Text.Substring(tb.SelectionStart, tb.SelectionLength));
        var t3 = FilterNonNum(tb.Text.Substring(tb.SelectionStart+tb.SelectionLength));
        tb.Text = t1 + t2 + t3;
        tb.SelectionStart = t1.Length;
        tb.SelectionLength = t2.Length;
    }
    
    private string FilterNonNum(string text)
    {
        return System.Text.RegularExpressions.Regex.Replace(text, "[^0-9\\.]*", "");
    }
    

    (t2いらない気もしますがまぁいいか...)

     

    • 回答としてマーク mucya 2011年10月28日 6:38
    2011年10月27日 10:06

すべての返信

  • USのフォーラムなども見てみましたが、InputScope="Digits"の場合、とりあえずは

    1. Key.Unknownが来たらe.PlatformKeyCodeをチェックする
    2. ハードウェアキーなどの特殊ケースは諦める

    しかなさそうです。

    なので無理にやるなら力技ですがこんな感じでいかがでしょうか?

    private readonly Key[] numeric = new Key[] 
        {
            Key.Back, Key.D0, Key.D1, Key.D2, Key.D3, Key.D4, Key.D5,
            Key.D6, Key.D7, Key.D8, Key.D9, Key.Unknown
        };
    
    private void text1_KeyDown(object sender, KeyEventArgs e)
    {
        if (Array.IndexOf(numeric, e.Key) == -1)
        {
            if (e.Key != Key.Unknown && e.PlatformKeyCode != 190)
                e.Handled = true;
        }
    }
    
    private void text1_KeyUp(object sender, KeyEventArgs e)
    {
        var tb = sender as TextBox;
        var t1 = FilterNonNum(tb.Text.Substring(0, tb.SelectionStart));
        var t2 = FilterNonNum(tb.Text.Substring(tb.SelectionStart, tb.SelectionLength));
        var t3 = FilterNonNum(tb.Text.Substring(tb.SelectionStart+tb.SelectionLength));
        tb.Text = t1 + t2 + t3;
        tb.SelectionStart = t1.Length;
        tb.SelectionLength = t2.Length;
    }
    
    private string FilterNonNum(string text)
    {
        return System.Text.RegularExpressions.Regex.Replace(text, "[^0-9\\.]*", "");
    }
    

    (t2いらない気もしますがまぁいいか...)

     

    • 回答としてマーク mucya 2011年10月28日 6:38
    2011年10月27日 10:06
  • kaorun様

    回答ありがとうございました。

    RealTextBoxクラスとか、NumberTextBoxクラスとか作成してみようと思いますが、道程は長~い(涙)

    2011年10月28日 6:50
  • 新しいクラスはできたのですが、キーボードが小さすぎると却下され

    数字入力用のページを作りました。

    このページに移動するときはパラメータを渡せるのですが、帰るときは入力された値を簡単には渡せないので、

    グローバルエリアに値をセットするようにしました。

    こういう使い方はイリーガル何でしょうか?

    2011年11月22日 6:48
  • イリーガルということはないと思いますが、Tombstoningなどアプリケーションライフサイクルを十分に考慮して設計した方が良いのではないかと思います。
    最悪、入力ページからタスクスイッチした場合メモリ上から廃棄され状態が復元できないこともあり得ます。

    Windows Phone 7 のトゥームストーン処理
    http://msdn.microsoft.com/ja-jp/magazine/hh148153.aspx

    ページ引数でデータのキーを与えて、データ本体はIsolatedStorageSettings.ApplicationSettings[]に保存しておく方が安全かもしれません。

    分離ストレージ(Isolated Storage)を使ってデータの保存と取得を行う - CH3COOH(酢酸)の実験室
    http://ch3cooh.jp/index.php/tips/windowsphone7/system/strage/using-isolated-storage/


    • 編集済み kaorun 2011年11月22日 12:19
    2011年11月22日 12:19
  • イリーガルということはないと思いますが、Tombstoningなどアプリケーションライフサイクルを十分に考慮して設計した方が良いのではないかと思います。
    最悪、入力ページからタスクスイッチした場合メモリ上から廃棄され状態が復元できないこともあり得ます。

    Windows Phone 7 のトゥームストーン処理
    http://msdn.microsoft.com/ja-jp/magazine/hh148153.aspx

    ページ引数でデータのキーを与えて、データ本体はIsolatedStorageSettings.ApplicationSettings[]に保存しておく方が安全かもしれません。

    分離ストレージ(Isolated Storage)を使ってデータの保存と取得を行う - CH3COOH(酢酸)の実験室
    http://ch3cooh.jp/index.php/tips/windowsphone7/system/strage/using-isolated-storage/


     

    上記トゥームストーンに関する文書を読ませて頂きましたが、私にはどうも納得がいきません。

    これってOSの手抜き?としか思えません。

    こんなことまで考慮してコーディングして、テストして(どうやってテストするのかもわかりませんが)・・・・効率悪すぎです。

    WPで業務アプリを作成するのは、まだ早いのかな?が私の感想です。

     

    2011年12月13日 7:09
  • OSの手抜き、というわけではなくて、そういう割り切り、と考えた方がよいと思います。

    ようするに、アプリケーションはフォアグラウンドではなくなったら常に終了させられることを覚悟しておけ、ということですね。
    WPはモバイル向けプラットフォームですから消費電力は極端に切りつめられるところまで切り詰めます。なので、バックグラウンドになったアプリケーションは一切CPUを使用しませんし、メモリからも早々に退去が求められます。なので、アプリは常に自分の値と状況を保存することが求められるわけです。

    まぁ、実際の所、Mango(WP7.5)以降の環境ではTombstoningはなかなか発生しなくはなっているんですが...。
    ちなみに、このようなバックグラウンドでの停止処理はWindows 8のMetro Style Appでも導入されるようです。

    新しいプラットフォームなので「今までのやり方」が通用しないことは多々ありますが、状況を把握して破たんしにくいViewModelを構築していければそんなに大変なことにはならないのではないかと思いますよ。

    2011年12月13日 7:26