none
TextChangedについて RRS feed

  • 質問

  • public partial class TextBoxAry : TextBox
    	{
    		public TextBoxAry():base()
    		{
    			
    			
    		}
    		private static TextBoxAry[,] txtBoxAry;
    		public TextBoxAry(int row, int col):base()
    		{
    			InitializeComponent();
    			Row = row;
    			Col = col;
    
    			txtBoxAry = new TextBoxAry[row, col];
    		
    		
    			for (int i = 0; i < row; i++)
    				for (int j = 0; j < col; j++)
    					txtBoxAry[i, j] = new TextBoxAry();
    		}
    
    		public override string ToString()
    		{
    			return "txtBoxAry[" + ROW.ToString() + "," + COL.ToString() + "]";
    		}
    		private static int Row, Col;
    
    		 
    		string txt = "";
    
    		public event TextChange TextChange; 
    		public override string Text
    		{
    			get
    			{
    				return base.Text;
    			}
    			set
    			{
    				base.Text = value;
    				
    				EventArgsAry args = new EventArgsAry(ROW, COL);
    				RaisePropertyChange();
    			}
    		}
    		private EventHandler onPropertyChange;
        [Description("プロパティ変更されたときに発生します。"),Category("アクション")]
        public event EventHandler PropertyChange 
        {
    			add
    			{
    				onPropertyChange += value;
    			}
    			remove
    			{
    				onPropertyChange -= value;
    			}
    		}
    
    
    		private void RaisePropertyChange()
    		{
    			EventArgsAry e = new EventArgsAry(ROW, COL);
    			OnPropertyChange(e);
    		}
    
    		protected virtual void OnPropertyChange(EventArgsAry e)
    		{
    			if (TextChange != null)
    			{
    				Debug.WriteLine(this.ToString());
    				
    				TextChange(this, e);
    			}
    		}
    		
    
    		public TextBoxAry this[int row, int col]
    		{
    			get
    			{
    				ROW = row;
    				COL = col;
    				
    				return txtBoxAry[row, col];
    			}
    			set
    			{
    				
    				txtBoxAry[row, col] = value;
    				ROW = row;
    				COL = col;
    			}
    		}
    		public int ROW
    		{
    			set { Row = value; }
    			private get { return Row; }
    		}
    		public int COL
    		{
    			set { Col = value; }
    			private get { return Col; }
    		}
    	}
    	public class EventArgsAry : EventArgs
    	{
    		
    
    		public EventArgsAry(int row, int col)
    		{
    			Row = row;
    			Col = col;
    		}
    
    		
    		int Row;
    		int Col;
    		
    		public int ROW
    		{
    			set { Row = value; }
    			get { return Row; }
    		}
    		public int COL
    		{
    			set { Col = value; }
    			get { return Col; }
    		}
    	}
    
    	public delegate void TextChange(object o, EventArgsAry e);
    
    }
    

    上記のようなクラスを作成して、インデックスでTextの変更をイベントを通じて確認したいんですが、UIからの入力を

    知るにはTextChangedイベントでないと確認できないです。どうすれば良いか教えてください。

    あと、上記のクラスの悪い部分があればそれも教えてほしいです。

    2010年11月9日 20:53

回答

  • static(静的)メンバーとインスタンスメンバーがぐちゃぐちゃです。よくまぁこれで動いてるなぁって印象。

    まず、TextBox1つ1つに持たせたい情報と、全体で1つに持たせたい情報に分けてみるといいかと。例えばRowフィールドが全体で1つなのにROWプロパティがTextBox1つ1つに独立して存在していますが、これって意図通りではないですよね?

    • 回答としてマーク 山本春海 2010年12月1日 4:16
    2010年11月9日 22:49
  • UIからの入力だとTextプロパティのSetterは通らないので動作してないんだと思います。OnTextChangedをoverrideすればお望みのことができるのではないでしょうか?

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    • 回答としてマーク 山本春海 2010年12月1日 4:16
    2010年11月10日 1:37
    モデレータ
  • コードからの推測なんですが、ExcelみたいにRow x Column個のTextBoxを並べてそれらを1つのイベントで受信したいんじゃないかと。

    でも個々のTextBoxもそれを束ねるクラスも共通のTextBoxAryクラスで表現されているために、個別のTextBoxで発生したTextChangedなのか、束ねた側のTextChangedなのか、区別がついていません。「OnTextChangedをoverride」と言っても「どこのOnTextChangedを?」って部分が理解できないと先に進めないかと。

    そういう意味で、staticとinstanceがぐちゃぐちゃと指摘しました。

    • 回答としてマーク 山本春海 2010年12月1日 4:16
    2010年11月10日 16:00
  • 私の書き方が悪かったみたいですね。すみません。基本的には佐祐理さんの補足のつもりで書きました。
    推測ばかりで申し訳ないのですが、私も佐祐理さんと同じように推測しています。たぶん、以下のような感じなのかなと。

       var tbary = new TextBoxAry(3, 3);

       var tba = tbary[1, 1];
       tba.Location = new System.Drawing.Point(50, 100);
       tba.TextChange += new TextChange(tba_TextChange);
       this.Controls.Add(tba);

       tba = tbary[1, 2];
       tba.Location = new System.Drawing.Point(50, 150);
       tba.TextChange += new TextChange(tba_TextChange);
       this.Controls.Add(tba);

    ただ、佐祐理さんも指摘されていますが、RowとColがstaticになっているので、TextChangeでどのTextBoxAryがクリックされたか判断できないと思います。個々のTextBoxAryのインスタンスを生成する時に、個々のインスタンスの情報として持たせてあげないとTextChangeイベントで個々のRowとColを取りようがないです。基本的にはこれだけで推測する動作はとりあえず実現できると思います。もちろん、RowとColのstaticを取るだけじゃなく、それに関する調整は必要だと思いますし、動作したとしてもそれが良いコードであるかどうかは別問題ですが。

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    2010年11月11日 2:10
    モデレータ
  • 皆さんの助言のおかげで無事したいことができました。

    ただ、まだまだおかしな点があると思うので助言してください。

    public partial class TextBoxAry : TextBox
    	{
    		
    		private static TextBoxAry[,] txtBoxAry;
    		
    		public TextBoxAry()
    		{
    			InitializeComponent();
    
    		}
    		
    		bool blnIsUserChange = true;
    
    		public TextBoxAry(int row, int col)
    			: base()
    		{
    			InitializeComponent();
    			
    			txtBoxAry = new TextBoxAry[row, col];
    			for (int i = 0; i < row; i++)
    				for (int j = 0; j < col; j++)
    				{
    					txtBoxAry[i, j] = new TextBoxAry();
    					
    				}
    
    		}
    
    		protected override void WndProc(ref Message m)
    		{
    			if (m.Msg == Win32Api.WM_SETTEXT || m.Msg == Win32Api.EM_REPLACESEL)
    			{
    				blnIsUserChange = false;
    			}
    			base.WndProc(ref m);
    		}
    		
    
    
    		public override string ToString()
    		{
    			return "txtBoxAry[" + ROW.ToString() + "," + COL.ToString() + "]";
    		}
    		private int Row, Col;
    
    
    		string txt = "";
    		public override string Text
    		{
    			get
    			{
    				return base.Text;
    			}
    			set
    			{
    				base.Text = value;
    				RaisePropertyChange();
    			}
    		}
    		public string TXT
    		{
    			get { return txtBoxAry[ROW, COL].txt; }
    			set { txtBoxAry[ROW, COL].txt = value; }
    		}
    
    		private EventHandler onPropertyChange;
    		public event EventHandler PropertyChange
    		{
    			add { onPropertyChange += value; }
    			remove { onPropertyChange -= value; }
    		}
    
    		public event TextChange TextChange;
    
    		protected virtual void OnPropertyChange(EventArgsAry ea)
    		{
    			if (TextChange != null)
    			{
    				Debug.WriteLine(this.ToString());
    
    				TextChange(this, ea);
    			}
    		}
    
    
    		private void RaisePropertyChange()
    		{
    			EventArgsAry args = new EventArgsAry(blnIsUserChange, ROW, COL);
    			OnPropertyChange(args);
    		}
    
    		public TextBoxAry this[int row, int col]
    		{
    			get
    			{
    				ROW = row;
    				COL = col;
    				return txtBoxAry[row, col];
    			}
    			set
    			{
    				txtBoxAry[row, col] = value;
    				ROW = row;
    				COL = col;
    			}
    		}
    		public int ROW
    		{
    			set { Row = value; }
    			get { return Row; }
    		}
    		public int COL
    		{
    			set { Col = value; }
    			get { return Col; }
    		}
    
    	}
    	public delegate void TextChange(object o, EventArgsAry ea);
    	public class EventArgsAry : EventArgs
    	{
    		int Row;
    		int Col;
    		private bool blnIsUserChanged;
    
    		public EventArgsAry(bool isUserChanged, int row, int col)
    		{
    			this.blnIsUserChanged = isUserChanged;
    			ROW = row;
    			COL = col;
    		}
    
    		public bool IsUserChanged
    		{
    			get
    			{
    				return blnIsUserChanged;
    			}
    		}
    		public int ROW
    		{
    			private set { Row = value; }
    			get { return Row; }
    		}
    		public int COL
    		{
    			private set { Col = value; }
    			get { return Col; }
    		}
    	}
    

    • 回答としてマーク 馬鹿1号 2010年12月8日 2:27
    2010年11月11日 23:17

すべての返信

  • static(静的)メンバーとインスタンスメンバーがぐちゃぐちゃです。よくまぁこれで動いてるなぁって印象。

    まず、TextBox1つ1つに持たせたい情報と、全体で1つに持たせたい情報に分けてみるといいかと。例えばRowフィールドが全体で1つなのにROWプロパティがTextBox1つ1つに独立して存在していますが、これって意図通りではないですよね?

    • 回答としてマーク 山本春海 2010年12月1日 4:16
    2010年11月9日 22:49
  • UIからの入力だとTextプロパティのSetterは通らないので動作してないんだと思います。OnTextChangedをoverrideすればお望みのことができるのではないでしょうか?

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    • 回答としてマーク 山本春海 2010年12月1日 4:16
    2010年11月10日 1:37
    モデレータ
  • コードからの推測なんですが、ExcelみたいにRow x Column個のTextBoxを並べてそれらを1つのイベントで受信したいんじゃないかと。

    でも個々のTextBoxもそれを束ねるクラスも共通のTextBoxAryクラスで表現されているために、個別のTextBoxで発生したTextChangedなのか、束ねた側のTextChangedなのか、区別がついていません。「OnTextChangedをoverride」と言っても「どこのOnTextChangedを?」って部分が理解できないと先に進めないかと。

    そういう意味で、staticとinstanceがぐちゃぐちゃと指摘しました。

    • 回答としてマーク 山本春海 2010年12月1日 4:16
    2010年11月10日 16:00
  • 私の書き方が悪かったみたいですね。すみません。基本的には佐祐理さんの補足のつもりで書きました。
    推測ばかりで申し訳ないのですが、私も佐祐理さんと同じように推測しています。たぶん、以下のような感じなのかなと。

       var tbary = new TextBoxAry(3, 3);

       var tba = tbary[1, 1];
       tba.Location = new System.Drawing.Point(50, 100);
       tba.TextChange += new TextChange(tba_TextChange);
       this.Controls.Add(tba);

       tba = tbary[1, 2];
       tba.Location = new System.Drawing.Point(50, 150);
       tba.TextChange += new TextChange(tba_TextChange);
       this.Controls.Add(tba);

    ただ、佐祐理さんも指摘されていますが、RowとColがstaticになっているので、TextChangeでどのTextBoxAryがクリックされたか判断できないと思います。個々のTextBoxAryのインスタンスを生成する時に、個々のインスタンスの情報として持たせてあげないとTextChangeイベントで個々のRowとColを取りようがないです。基本的にはこれだけで推測する動作はとりあえず実現できると思います。もちろん、RowとColのstaticを取るだけじゃなく、それに関する調整は必要だと思いますし、動作したとしてもそれが良いコードであるかどうかは別問題ですが。

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    2010年11月11日 2:10
    モデレータ
  • 皆さんの助言のおかげで無事したいことができました。

    ただ、まだまだおかしな点があると思うので助言してください。

    public partial class TextBoxAry : TextBox
    	{
    		
    		private static TextBoxAry[,] txtBoxAry;
    		
    		public TextBoxAry()
    		{
    			InitializeComponent();
    
    		}
    		
    		bool blnIsUserChange = true;
    
    		public TextBoxAry(int row, int col)
    			: base()
    		{
    			InitializeComponent();
    			
    			txtBoxAry = new TextBoxAry[row, col];
    			for (int i = 0; i < row; i++)
    				for (int j = 0; j < col; j++)
    				{
    					txtBoxAry[i, j] = new TextBoxAry();
    					
    				}
    
    		}
    
    		protected override void WndProc(ref Message m)
    		{
    			if (m.Msg == Win32Api.WM_SETTEXT || m.Msg == Win32Api.EM_REPLACESEL)
    			{
    				blnIsUserChange = false;
    			}
    			base.WndProc(ref m);
    		}
    		
    
    
    		public override string ToString()
    		{
    			return "txtBoxAry[" + ROW.ToString() + "," + COL.ToString() + "]";
    		}
    		private int Row, Col;
    
    
    		string txt = "";
    		public override string Text
    		{
    			get
    			{
    				return base.Text;
    			}
    			set
    			{
    				base.Text = value;
    				RaisePropertyChange();
    			}
    		}
    		public string TXT
    		{
    			get { return txtBoxAry[ROW, COL].txt; }
    			set { txtBoxAry[ROW, COL].txt = value; }
    		}
    
    		private EventHandler onPropertyChange;
    		public event EventHandler PropertyChange
    		{
    			add { onPropertyChange += value; }
    			remove { onPropertyChange -= value; }
    		}
    
    		public event TextChange TextChange;
    
    		protected virtual void OnPropertyChange(EventArgsAry ea)
    		{
    			if (TextChange != null)
    			{
    				Debug.WriteLine(this.ToString());
    
    				TextChange(this, ea);
    			}
    		}
    
    
    		private void RaisePropertyChange()
    		{
    			EventArgsAry args = new EventArgsAry(blnIsUserChange, ROW, COL);
    			OnPropertyChange(args);
    		}
    
    		public TextBoxAry this[int row, int col]
    		{
    			get
    			{
    				ROW = row;
    				COL = col;
    				return txtBoxAry[row, col];
    			}
    			set
    			{
    				txtBoxAry[row, col] = value;
    				ROW = row;
    				COL = col;
    			}
    		}
    		public int ROW
    		{
    			set { Row = value; }
    			get { return Row; }
    		}
    		public int COL
    		{
    			set { Col = value; }
    			get { return Col; }
    		}
    
    	}
    	public delegate void TextChange(object o, EventArgsAry ea);
    	public class EventArgsAry : EventArgs
    	{
    		int Row;
    		int Col;
    		private bool blnIsUserChanged;
    
    		public EventArgsAry(bool isUserChanged, int row, int col)
    		{
    			this.blnIsUserChanged = isUserChanged;
    			ROW = row;
    			COL = col;
    		}
    
    		public bool IsUserChanged
    		{
    			get
    			{
    				return blnIsUserChanged;
    			}
    		}
    		public int ROW
    		{
    			private set { Row = value; }
    			get { return Row; }
    		}
    		public int COL
    		{
    			private set { Col = value; }
    			get { return Col; }
    		}
    	}
    

    • 回答としてマーク 馬鹿1号 2010年12月8日 2:27
    2010年11月11日 23:17