locked
TextBoxのGotFocusで値が変えられても、全選択状態を維持したい。 RRS feed

  • 質問

  • 損と申します。
    Silverlight4+VS2010+Blend4で開発しております。

    WindowsFormsアプリケーションからの移植で、Silverlightアプリケーションを作成しているのですが、TextBoxのSelectAll()メソッドの動きの違いで困ってしまいました。
    やりたいこととしては、MyTextBoxというカスタムコントロール(TextBox継承)がフォーカスを受け取った時に、テキストを全選択状態にしたいです。
    この時、開発者コードのGotFocusでテキストを変更されると、WindowsFormsでは全選択が維持されるのに対し、Silverlightでは全選択が解除されてしまいます。

    Silverlightの動きをWindowsForms風にするためには、どのようにすれば良いでしょうか。


    ■WindowsFormsアプリケーションコードサンプル

    // TextBoxのカスタムコントロール
    public class MyTextBox : TextBox
    {
     public MyTextBox()
      : base()
     {
     }

     protected override void OnEnter(EventArgs e)
     {
      base.OnEnter(e);
      // このSelectAll()は、開発者のEnter処理よりも後に呼ばれる
      SelectAll();
     }
    }

    // MyTextBoxを貼り付けたアプリの処理
    public partial class Form1 : Form
    {
     public Form1()
     {
      InitializeComponent();
     }

     private void myTextBox1_Enter(object sender, EventArgs e)
     {
      this.myTextBox1.Text = "123456789";
     }
    }


    ■Silverlightアプリケーションコードサンプル

    // TextBoxのカスタムコントロール
    public class MyTextBox : TextBox
    {
     public MyTextBox()
      : base()
     {
     }

     protected override void OnGotFocus(RoutedEventArgs e)
     {
      base.OnGotFocus(e);
      // このSelectAll()は、開発者のGotFocus処理よりも先に呼ばれる
      this.SelectAll();
     }
    }

    // MyTextBoxを貼り付けたアプリの処理
    public partial class MainPage : UserControl
    {
     public MainPage()
     {
      InitializeComponent();
     }

     private void myTextBox1_GotFocus(object sender, RoutedEventArgs e)
     {
      this.myTextBox1.Text = "123456789";
     }
    }

    2011年8月8日 2:34

回答

  • Silverlightでのルーティングイベントは損さんのおっしゃられているWinFormのような派生先でのイベント処理は行えないようです。

    実際にSilverlightでのルーティングイベントでのRoutedEventArgsではHandledプロパティがありません。

    デバッグして処理の流れを見て頂くと分かると思いますが、MyTextBoxクラスのOnGotFocusメソッド内で呼び出しているbase.OnGotFocusが実行されても、派生先のTextBoxのGotFocusイベントハンドラが呼ばれていないと思います。MyTextBoxクラスのOnGotFocusメソッドが完全に抜けてから派生先のGotFocusイベントハンドラが呼び出されます。

    これは派生先でのイベントの処理可否を制御出来ない事を示しています。これをWinFormのような挙動で実装したいとすれば、独自のイベントを実装させ、OnGotFocusメソッドないでそのイベントを発行させ、派生先でイベント処理させるなどの実装をしないといけないようです。

    以下のような感じでWinFormのような実装は可能です。

     

    public class MyTextBox : TextBox
    {
    	public event EventHandler GotFocusEx;
    
    	protected virtual void OnGotFocusEx(EventArgs e)
    	{
    		var handler = this.GotFocusEx;
    		if (handler != null)
    			handler(this, e);
    	}
    
    	public MyTextBox()
    		:base()
    	{}
    
    	protected override void OnGotFocus(RoutedEventArgs e)
    	{
    		base.OnGotFocus(e);
    
    		this.OnGotFocusEx(EventArgs.Empty);
    
    		this.SelectAll();
    	}
    }
    
    public partial class MainPage : UserControl
    {
    	public MainPage()
    	{
    		InitializeComponent();
    	}
    
    	private void myTextBox1_GotFocusEx(object sender, EventArgs e)
    	{
    		this.myTextBox1.Text = "123456789";
    	}
    }
    


     


    ★良い回答には回答済みマークを付けよう! Blog : http://blogs.wankuma.com/kzt/ Blog : http://www.blogs.uxlabo.net/kazuto/


    • 回答としてマーク 2011年8月8日 6:13
    2011年8月8日 5:52

すべての返信

  • Silverlightでのルーティングイベントは損さんのおっしゃられているWinFormのような派生先でのイベント処理は行えないようです。

    実際にSilverlightでのルーティングイベントでのRoutedEventArgsではHandledプロパティがありません。

    デバッグして処理の流れを見て頂くと分かると思いますが、MyTextBoxクラスのOnGotFocusメソッド内で呼び出しているbase.OnGotFocusが実行されても、派生先のTextBoxのGotFocusイベントハンドラが呼ばれていないと思います。MyTextBoxクラスのOnGotFocusメソッドが完全に抜けてから派生先のGotFocusイベントハンドラが呼び出されます。

    これは派生先でのイベントの処理可否を制御出来ない事を示しています。これをWinFormのような挙動で実装したいとすれば、独自のイベントを実装させ、OnGotFocusメソッドないでそのイベントを発行させ、派生先でイベント処理させるなどの実装をしないといけないようです。

    以下のような感じでWinFormのような実装は可能です。

     

    public class MyTextBox : TextBox
    {
    	public event EventHandler GotFocusEx;
    
    	protected virtual void OnGotFocusEx(EventArgs e)
    	{
    		var handler = this.GotFocusEx;
    		if (handler != null)
    			handler(this, e);
    	}
    
    	public MyTextBox()
    		:base()
    	{}
    
    	protected override void OnGotFocus(RoutedEventArgs e)
    	{
    		base.OnGotFocus(e);
    
    		this.OnGotFocusEx(EventArgs.Empty);
    
    		this.SelectAll();
    	}
    }
    
    public partial class MainPage : UserControl
    {
    	public MainPage()
    	{
    		InitializeComponent();
    	}
    
    	private void myTextBox1_GotFocusEx(object sender, EventArgs e)
    	{
    		this.myTextBox1.Text = "123456789";
    	}
    }
    


     


    ★良い回答には回答済みマークを付けよう! Blog : http://blogs.wankuma.com/kzt/ Blog : http://www.blogs.uxlabo.net/kazuto/


    • 回答としてマーク 2011年8月8日 6:13
    2011年8月8日 5:52
  • ご返信、有難うございます。
    和人さんの回答内容の実装で実現できました。助かりました。
    有難うございます。
    2011年8月8日 6:13