18110


よろしくお願いします。

c#とSQLiteでWindowsフォームアプリケーションを作成しています。  
VisualStudio Community 2015, windows8.1を使用しています。

複数あるボタンのうち１つをクリックすると、対応するTextBoxに「○」を出力させるという動きをさせたいと思っています。

Button1をクリック → TextBox aaa,TextBox bbb に「○」が出力される  
Button2をクリック → TextBox aaa,TextBox ccc に「○」が出力される

このようなイメージです。

ボタンをクリックした時に○が出力されるTextBoxのnameはDBに入っており、  
select文で抽出する所までは出来ています。

[code]

    using(SQLiteDaraReader reader = command.ExecuteReader())
    {
       while(reader.Read())
       {
          reader["TBox_name"].Text = "○";
       }
    }
    
[/code]

上記の形で試しましたが、失敗しました。

私がやりたい事が上記のコードで伝わっているでしょうか？

<http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1147000486>  
こちらが一番参考になりそうだと思ったのですが、  
TextBoxの配列に直接書き込んでいるので私のやりたいこととは違いました。

<http://oshiete.goo.ne.jp/qa/6273058.html>  
こちらも参考になるかと思いましたが、やはり直接書き込んでいます。

私もTxtBoxの配列にnameを入れてみようと思って試しましたが、

[code]

    using(SQLiteDaraReader reader = command.ExecuteReader())
    {
       while(reader.Read())
       {
          TextBox[] wTextBox = { reader["TBox_name"] };
       }
    }
    
[/code]

objectやstringはTextBoxに変換できないとの事なので、困っています。

参考になるサイトや意見など何でも良いので情報が欲しいです。  
よろしくお願いします。


CC BY-SA 3.0
2015-10-27T02:53:39.020
18105
2015-10-27T06:41:44.633
2015-10-27T05:40:54.953
2383
12797
question
c#
c#フォームアプリでTextBoxのnameを動的に指定したい


[Controlsプロパテ](https://msdn.microsoft.com/ja-
jp/library/system.windows.forms.control.controls\(v=vs.110\).aspx)ィを使用することで動的にコントロールを選択することができます。

[code]

    Controls["bbb"].Text = "○";
    
[/code]

* * *

コメントに書かれたコードが無茶苦茶です。

[code]

    string c = reader["koumoku_nm"].ToString();
    if (c != null) {
        Controls["(reader['koumoku_nm'])"].Text = "○";
    }
    
[/code]

まず`null`かどうかを判定する前にToString()を呼び出してしまっていますので、「オブジェクト参照がオブジェクト
インスタンスに設定されていません。」が発生する要因です。  
また動的にコントロールを選択するのではなく **"(reader['koumoku_nm'])"**
という名前のコントロールを探そうとしています。そんな名前は存在するはずがありません。


CC BY-SA 3.0
2015-10-27T03:45:21.180
18109
2015-10-27T06:41:44.633
2015-10-27T06:41:44.633
4236
4236
18105
answer


`Controls`プロパティのstringインデクサはあくまで`Controls`内しか検索しないため、フォーム直下に存在しない一般の場合では再帰的に処理を行う必要があります。

実装例を挙げると以下のようになります。`Find`は指定したコントロール(=`parent`)の子孫にある`Name`が`name`のコントロールを探すメソッドです。

[code]

    private static Control Find(Control parent, string name)
    {
        // まずparentの子コントロールでnameを検索します。
        var r = parent.Controls[name];
    
        // 子コントロールでnameが見つかった場合、該当コントロールを返します。
        if (r != null)
        {
            return r;
        }
    
        // parentの子コントロールでnameが見つからなかった場合、今度は子コントロールでFindを実行します。
        foreach (Control c in parent.Controls)
        {
            // TODO:必要ならcに対する条件を追加します。
    
            // 子コントロールcを起点にしてnameを検索します。
            r = Find(c, name);
            if (r != null)
            {
                // cの子孫にnameが見つかった場合、該当コントロールを返します。
                return r;
            }
        }
    
        // nameが見つからなかった場合、nullを返します。
        return null;
    }
    
[/code]

またリフレクションを用いてフィールドを探すこともできます。

[code]

    typeof(Form1).GetField(textBox1.Name, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).GetValue(this)
    
[/code]


CC BY-SA 3.0
2015-10-27T04:08:25.020
18110
2015-10-27T05:52:42.917
2015-10-27T05:52:42.917
5750
5750
18105
answer


そもそも、DBから直接TextBoxを操作しようとしているのが間違っています。  
ドメイン(データベースなどへの操作)とビュー(表示)は、分離すべきです。

代わりにINotifyPropertyChangedを実装したクラスを定義します。

[code]

    class TextData : System.ComponentModel.INotifyPropertyChanged {
         public string Text {
             get{
                 return this._Text;
             }
             set {
                if( this._Text == value )
                   return;
                this._Text = value;
                this.PropertyChanged?.Invoke( this , new PropertyChangedEventArgs( nameof(Text) ) );
             }
         }
         private string _Text;
    
         public event PropertyChangedEventHandler PropertyChanged;
    }
    
[/code]

ドメイン(今回の場合DB)からの入出力は、このTextDataクラスに対して行います。

**フォームの処理**

フォームでは、TextBoxにTextDataオブジェクトをデータバインディングします。

[code]

    textbox1.DataBindings( nameof( TextBox.Text ) ,
       textdata1 , nameof(TextData.Text) , true , 
       DataSourceUpdateMode.Never );
    
[/code]

textdata1は、TextDataクラスのオブジェクトです。  
このようにすることで、textdata1オブジェクトのTextプロパティが変更されると、  
textbox1(TextBox)のTextプロパティが更新されるようになります。

**データベースの処理**

データベースからは、TextBoxではなく、textdata1に対する操作に変更します。

[code]

    using(SQLiteDaraReader reader = command.ExecuteReader())　{
        while(reader.Read()) {
          textdata1.Text = "○";
       }
    }
    
[/code]

上記の例では、直接 textdata1 と指定していますがDictionaryなどを用いて管理しても構いません。


CC BY-SA 3.0
2015-10-27T06:03:35.670
18121
2015-10-27T06:03:35.670
2207
18105
answer