none
Windowフォーム 画面オブジェクト と LINQ 実行される順序 RRS feed

  • 質問

  • Windowsフォームで 画面オブジェクトに対して LINQ を使っています。

    その際の実行する順序は、必ず同一なのか分からず、悩んでおります。

    実装したい内容ですが、画面のTextBoxに値を表示、List型の変数に格納、

    ユーザの操作後に、TextBoxの値に変更がないか比較をしたいというものです。

    ソースとしては、以下のようなものです。

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

                List<string> lstValue = new List<string>();

                var textBox = Controls.OfType<TextBox>();

                foreach (var c in textBox)
                {
                    lstValue.Add(c.Text); //格納して、後で比較を行いたい
                }

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

    色々と調べてみましたが、解決に至らず、どなたかご教授いただければ幸いです。

    宜しくお願い致します。

    2018年11月28日 13:30

回答

  • ご質問のようなコードで TextBox の順序は、z オーダーが最も手前から奥側に向かっての順序になるようです。具体的には、一番最後に配置された TextBox が先頭で、最後から2番目に配置した TextBox が次となるような順序です。

    プログラムからコントロールに対して BringToFront メソッドや SendToBack メソッドを呼んで z オーダーを変更しない限り、ユーザーの操作では、z オーダーは変わらないなずですので、テキストの変更が無いか比較する際には使えるのではないかと思います。

    もし気になるようでしたら、

    var textBox = Controls.OfType<TextBox>().OrderBy(d => d.TabIndex);

    というように、TabIndex の順で並び替えるのもありかもしれません。

    参考サイト:
    https://stackoverflow.com/questions/11335529/going-through-controls-in-order
    https://stackoverflow.com/questions/28664910/textbox-order-by-tabindex
    http://www.atmarkit.co.jp/ait/articles/0505/13/news116.html

    2018年11月28日 13:57
  • Windowsフォームで 画面オブジェクトに対して LINQ を使っています。

    その際の実行する順序は、必ず同一なのか分からず、悩んでおります。

    提示されているコード内で LINQ は OfType メソッドをつなげただけなので、順序は Controls プロパティに依存します。
    つまり、「今のコードだと LINQ は順序に関係ない」ということになります。
    Controls プロパティの順序についてはすでにコメントがありますね。

    ちなみに、データ量最小なら List<string> かもしれませんが、そういった順序などの不安を払拭するなら、Dictionary<TextBox, string> にして「Keys 数の一致」「一方の Key を元に Value を取り出し、他方から TryGetValue で取り出し、Value 同志を比較するループ」とすることで、順序は気にしなくて済みます。
    2018年11月28日 21:18
    モデレータ
  • もし、各TextBoxのTagに何もセットしていないのであれば下記のようにTagにしまっておくという方法もあります。

    foreach( var c in textBox )
    {
      c.Tag = c.Text;
    }
    

    比較時は下記のような感じ。

    foreach( var c in textBox )
    {
      if( c.Tag != c.Text )
      {
         // 違うので何か処理する
         // 以後継続不要なら break; でループを抜ける
      }
    }

    同一のオブジェクト内にデータを格納しているので、分離してしまう可能性もなく比較も安直に行えます。



    とっちゃん@わんくま同盟, Visual Studio and Development Technologies http://blogs.wankuma.com/tocchann/default.aspx

    2018年11月29日 4:53

すべての返信

  • ご質問のようなコードで TextBox の順序は、z オーダーが最も手前から奥側に向かっての順序になるようです。具体的には、一番最後に配置された TextBox が先頭で、最後から2番目に配置した TextBox が次となるような順序です。

    プログラムからコントロールに対して BringToFront メソッドや SendToBack メソッドを呼んで z オーダーを変更しない限り、ユーザーの操作では、z オーダーは変わらないなずですので、テキストの変更が無いか比較する際には使えるのではないかと思います。

    もし気になるようでしたら、

    var textBox = Controls.OfType<TextBox>().OrderBy(d => d.TabIndex);

    というように、TabIndex の順で並び替えるのもありかもしれません。

    参考サイト:
    https://stackoverflow.com/questions/11335529/going-through-controls-in-order
    https://stackoverflow.com/questions/28664910/textbox-order-by-tabindex
    http://www.atmarkit.co.jp/ait/articles/0505/13/news116.html

    2018年11月28日 13:57
  • Windowsフォームで 画面オブジェクトに対して LINQ を使っています。

    その際の実行する順序は、必ず同一なのか分からず、悩んでおります。

    提示されているコード内で LINQ は OfType メソッドをつなげただけなので、順序は Controls プロパティに依存します。
    つまり、「今のコードだと LINQ は順序に関係ない」ということになります。
    Controls プロパティの順序についてはすでにコメントがありますね。

    ちなみに、データ量最小なら List<string> かもしれませんが、そういった順序などの不安を払拭するなら、Dictionary<TextBox, string> にして「Keys 数の一致」「一方の Key を元に Value を取り出し、他方から TryGetValue で取り出し、Value 同志を比較するループ」とすることで、順序は気にしなくて済みます。
    2018年11月28日 21:18
    モデレータ
  • もし、各TextBoxのTagに何もセットしていないのであれば下記のようにTagにしまっておくという方法もあります。

    foreach( var c in textBox )
    {
      c.Tag = c.Text;
    }
    

    比較時は下記のような感じ。

    foreach( var c in textBox )
    {
      if( c.Tag != c.Text )
      {
         // 違うので何か処理する
         // 以後継続不要なら break; でループを抜ける
      }
    }

    同一のオブジェクト内にデータを格納しているので、分離してしまう可能性もなく比較も安直に行えます。



    とっちゃん@わんくま同盟, Visual Studio and Development Technologies http://blogs.wankuma.com/tocchann/default.aspx

    2018年11月29日 4:53
  • kenjinote様

    ご教授ありがとうございます。

    >プログラムからコントロールに対して BringToFront メソッドや SendToBack メソッドを呼んで z オーダーを変更しない
    >限り、ユーザーの操作では、z オーダーは変わらないなずですので

    ありがとうございます。安心いたしました。
    また、参考サイトのご紹介もありがとうございます。


    >というように、TabIndex の順で並び替えるのもありかもしれません。
    なるほど、それなら間違いありませんね。
    目から鱗でした。


    >TextBox の順序は、z オーダーが最も手前から奥側に向かっての順序になるようです。
    >具体的には、一番最後に配置された TextBox が先頭で

    Z方向のことは全く念頭にありませんでした。

    お忙しいところ、お時間、お手間を頂き誠にありがとうございました。
    2018年11月29日 15:27
  • Azulean様

    ご教授ありがとうございます。

    >そういった順序などの不安を払拭するなら、
    >Dictionary<TextBox, string> にして「Keys 数の一致」「一方の Key を元に Value を取り出

    おっしゃる通り、Dictionary型なら間違いなく、その実装方法も考えたのですが、
    そもそも、例に挙げたような、コーディングでも、順が保証されてもよいのではないだろうかと
    考え、質問をあげさせていただきました。

    お忙しいところ、お時間、お手間を頂き誠にありがとうございました。
    2018年11月29日 15:32
  • とっちゃん@わんくま同盟様

    ご教授ありがとうございます。

    >もし、各TextBoxのTagに何もセットしていないのであれば下記のようにTagにしまっておくという方法もあります。

    なるほど!!
    非常にすっきりした、扱いやすいコーディングになりますね。
    目から鱗でした。

    ただ、既に、Tagプロパティは他の値に使用しているため、自身の今回の実装では
    逆に煩雑になりそうです。

    ただ、この方法は、別の機会に活かせそうです。

    お忙しいところ、お時間、お手間を頂き誠にありがとうございました。
    2018年11月29日 15:37
  • みなさんからの回答の総括みたいなコメント、「そもそも」論のコメントなのですが・・・、

    元の複数のTextBoxは、ぴるのすけさんの意図として、それぞれ「個性」があるのでしょうか? 番号が割り当てられているとか、名前が割り当てられているとか。それとも「個性無し」の単なる集合でしょうか? それによって最初のご質問の実行順序が同一であることが、必要なのか、不要なのか議論が分かれてくると思います。

    「個性無し」の単なる集合なら、「そもそも」実は順序が同じじゃなくてもよいようにも思います。これだと非常に気楽。

    実行順序を規則づける必要があるなら、何によって管理するかを決める必要があります。複数のTextBoxはデザイン時に静的に配置されて既に固定されているのか、デザイン時に静的に配置されるのだがまだデザインは変わり得るのか、実行時に動的に配置さるのか? デザインイン時にzオーダーやtabオーダーで管理するか、Tagに何か書き込むか、実行時に動的にこれらのプロパティーを割り当てて管理するか? いろいろなオプションがあり得ると思います。

    2018年11月29日 22:59
  • 外池様

    コメントいただきありがとうございます。
    新しいレスポンスを頂いていることに気付かず、返信が遅くなり大変申し訳ありません。


    >「個性無し」の単なる集合なら、「そもそも」実は順序が同じじゃなくてもよいようにも思います。
    >これだと非常に気楽。

    機能的に、順序は守られなくても問題ないものです。
    質問としておかしなものであったら、申し訳ありません。

    ただ、LINQの内部構造としてどう実行されているか、知りたいと思い、質問させていただきました。
    2018年12月9日 8:53