none
BindingSource(接続データベースはAccess)を利用したWindowsフォームでのフィルター操作についてご質問があります。 RRS feed

  • 質問

  • BindingSource(接続データベースはAccessを利用したWindowsフォームでの操作でご質問があります。
    Aフォーム、Bフォーム共にDataGridView上に「商品ID」(Access上は数値型)と言うフィールドがあります。
    AフォームのDataGridView上のボタンを押した時のイベントでBフォームを開く時、AフォームのDataGridView上で選択した行の
    「商品
    ID」の値と同じ値を持つデータをBフォームでフィルタして表示したいと思っております。

    ◆Aフォームで取得した「商品ID」をPublicな変数としてprogramに「Itemid」と定義しました。

    // Aフォーム上で取得した商品IDpublicな変数に定義

            public static string Itemid { get; set; }

    ◆AフォームのDataGridView上のボタンが押された時のイベントはこのようになっています。

        /// <summary>
            /// AフォームのDataGridView上のボタンが押された時
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void DGV_AP_CellContentClick(object sender, DataGridViewCellEventArgs e)

            {

                DataGridView dgv = (DataGridView)sender;

                    //"購入記録"列ボタンがクリックされた時
                    if (dgv.Columns[e.ColumnIndex].Name == "購入記録")

                    {

                    //選択行の商品IDの値を取得
                    Program.Itemid = Convert.ToString(dgv.CurrentRow.Cells[1].Value);               

                    //Bフォームを開く
                    PurchaseRecordForm prForm = new PurchaseRecordForm();
                    DialogResult drRet = prForm.ShowDialog();

                }

    ◆Bフォームを読み込む時のイベントです

        /// <summary>
            /// Bフォーム読み込み時
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void PurchasePecordForm_Load(object sender, EventArgs e)
            {

              // TODO: このコード行はデータを 'purchaseRecordDataSet.PurchaseRecordDataTable' テーブルに読み込みます。
          必要に応じて移動、または削除をしてください。

                this.purchaseRecordTableAdapter.Fill(this.purchaseRecordDataSet.PurchaseRecordDataTable);

                //フィルタ表示
                purchaseRecordDataTableBindingSource.Filter = "商品ID = Program.Itemid";

            }

    上記で操作すると「ハンドルされていない例外」として

    System.Data.EvaluateException '[Program.Itemid]が見つかりません。」となってしまいました。
    どのように修正すれば良いかお教えいただけないでしょうか。
    C#は初心者で分からないことも多く、恐れ入りますがよろしくお願い致します。

    2018年5月15日 6:13

回答

  • purchaseRecordDataTableBindingSource.Filter = "商品ID = " + Program.Itemid;
    で、大丈夫だと思います。
    purchaseRecordDataTableBindingSource.Filter = "商品ID = Program.Itemid"
    では、"商品ID = Program.Itemid"の文字列のままがFilterにセットされます。つまり、Program.Itemidの部分が値に変換されて渡されません。
    また、Visual Studioのバージョンはいくつをお使いでしょうか? Visual Studio 2015、.NET Framework 4.6以降では以下のようにも書けます。以下のように書くと、Program.Itemidの部分がその値に変換された後に、Filterに渡されます。
    purchaseRecordDataTableBindingSource.Filter = $"商品ID = {Program.Itemid}";

    さて、上記のような静的な変数経由で値を渡すのはあまり関心しません。
    PurchaseRecordForm prForm = new PurchaseRecordForm(Convert.ToString(dgv.CurrentRow.Cells[1].Value));
    のように、フォームBのコンストラクタの引数として渡すのが良いでしょう。
    この場合、フォームBにこの引数付きのコンストラクタを定義し、この引数経由でConvert.ToString(dgv.CurrentRow.Cells[1].Value)の値をフォームBで取得することができます。

    ついでに言えば、Filterで絞るのではなく、以下のようにFillメソッドの引数として渡した方が良いでしょう。
    当然ですが、Fillメソッドがこの引数を持つように、TableAdapterを作り直す必要があります。
    this.purchaseRecordTableAdapter.Fill(this.purchaseRecordDataSet.PurchaseRecordDataTable, 商品ID);
    そうしないと毎回、使いもしないデータをフォームBは裏で読み込んでいることになります。

    (追記)
    .NET Framework 4.6以降ではなく、.NET Framework 2.0以降ということです。
    お詫びし、訂正いたします。


    ★良い回答には質問者は回答済みマークを、閲覧者は投票を!




    • 編集済み trapemiyaModerator 2018年5月15日 9:56 追記
    • 回答としてマーク sasatomo 2018年5月16日 2:15
    • 回答としてマークされていない sasatomo 2018年5月16日 3:37
    • 回答としてマーク sasatomo 2018年5月16日 4:12
    2018年5月15日 6:49
    モデレータ
  • PurchaseRecordForm prForm =

    new PurchaseRecordForm(Convert.ToString(dgv.CurrentRow.Cells[1].Value));
    書き直して
    フォームBのコンストラクタの引数として渡してみましたが
    PurchaseRecordFormの部分に赤波線がつきエラーになりました。

    引数付きのコンストラクタがPurchaseRecordFormに定義されていないからでしょう。
    以下を参考にして、
    PurchaseRecordFormに引数付きのコンストラクタを定義してみて下さい。

    (参考)
    コンストラクタ
    http://www.kisoplus.com/kihon/const.html

    また、Filterで絞らず、Fillメソッドの引数としてthis.purchaseRecordTableAdapter.Fill(this.purchaseRecordDataSet.PurchaseRecordDataTable, 商品ID);と書いてみましたが、

    商品IDの部分に赤い波線がついてエラーになりました。
    PurchaseRecordDataTableには確かに商品IDはあります。)

    前述した通り、TableAdapterを作成し直す必要があります。既存のpurchaseRecordTableAdapterを右クリックして「構成」を選び、表示されたSQLのselect文に、whereを以下のように追加してみて下さい。
    select
    ・・・
    from PurchaseRecordDataTable
    where 商品ID = @商品ID

    ちなみに@を付けるとパラメータの意味になります。上記では@商品IDとしてわかりやすいパラメータ名にしましたが、名前は何でも構いません。例えば、@商品あいでぃ とかでも良いです。しかし、わかりやすいので一般的には列名とパラメータ名は合わせます。

    さて、このスレッドのタイトルと、上記の質問内容は合わなくなってきています。上記のアドバイスで追加のご質問があれば、新たにスレッドを立ててご質問下さい。よろしくお願いいたします。


    ★良い回答には質問者は回答済みマークを、閲覧者は投票を!

    2018年5月16日 4:49
    モデレータ
  • 細かいことで本筋からは外れますが、2017だと以下のようにも書けるということです。

    purchaseRecordDataTableBindingSource.Filter = $"商品ID = {Program.Itemid}";

    上記の$を使った書き方はC# 6で追加された機能で、string interpolation(文字列補間)と呼ばれますが、.NET Framework 2.0以降で動くようです。訂正とお詫びをいたします。

    string interpolation
    http://ufcpp.net/study/csharp/cheatsheet/listfxlangversion/


    ★良い回答には質問者は回答済みマークを、閲覧者は投票を!

    • 回答としてマーク sasatomo 2018年5月16日 2:16
    2018年5月15日 9:54
    モデレータ
  • BindingSourceを利用したWindowsフォームでのフィルター操作についてさん
    こんにちは、フォーラム オペレーターの立花です。
    MSDN フォーラムへご投稿くださいましてありがとうございます。

    trapemiya さんから頂いた回答はお役に立ちましたでしょうか。
    同じ問題であとから参照した方が、素早く情報を取得できるように、
    参考になった回答には、その投稿に [回答としてマーク] をご設定ください。

    お手数ですが、ご協力の程、どうぞよろしくお願いいたします。

    フォーラム利用時の注意点のお知らせです。
    ※初めてご投稿された方を対象にお知らせしています。

    ご利用の際は、下記内容をお守りいただきますと
    情報が寄せられやすくなりますので、ぜひご一読ください。
    フォーラムでご質問頂くにあたっての注意点
    フォーラムのご利用方法(質問の投稿)について
    フォーラムへの回答に関するガイドラインおよびフォーラム運営について(再掲)
    ご意見、ご要望はこちらのフォーラムまで。
    各種設定方法はフォーラム内を [かんたん フォーラム ガイド] で検索してみてください。


    参考になった投稿には回答としてマークの設定にご協力ください
    MSDN/TechNet Community Support 立花楓

    • 回答としてマーク sasatomo 2018年5月16日 2:25
    2018年5月16日 2:01
    モデレータ

すべての返信

  • purchaseRecordDataTableBindingSource.Filter = "商品ID = " + Program.Itemid;
    で、大丈夫だと思います。
    purchaseRecordDataTableBindingSource.Filter = "商品ID = Program.Itemid"
    では、"商品ID = Program.Itemid"の文字列のままがFilterにセットされます。つまり、Program.Itemidの部分が値に変換されて渡されません。
    また、Visual Studioのバージョンはいくつをお使いでしょうか? Visual Studio 2015、.NET Framework 4.6以降では以下のようにも書けます。以下のように書くと、Program.Itemidの部分がその値に変換された後に、Filterに渡されます。
    purchaseRecordDataTableBindingSource.Filter = $"商品ID = {Program.Itemid}";

    さて、上記のような静的な変数経由で値を渡すのはあまり関心しません。
    PurchaseRecordForm prForm = new PurchaseRecordForm(Convert.ToString(dgv.CurrentRow.Cells[1].Value));
    のように、フォームBのコンストラクタの引数として渡すのが良いでしょう。
    この場合、フォームBにこの引数付きのコンストラクタを定義し、この引数経由でConvert.ToString(dgv.CurrentRow.Cells[1].Value)の値をフォームBで取得することができます。

    ついでに言えば、Filterで絞るのではなく、以下のようにFillメソッドの引数として渡した方が良いでしょう。
    当然ですが、Fillメソッドがこの引数を持つように、TableAdapterを作り直す必要があります。
    this.purchaseRecordTableAdapter.Fill(this.purchaseRecordDataSet.PurchaseRecordDataTable, 商品ID);
    そうしないと毎回、使いもしないデータをフォームBは裏で読み込んでいることになります。

    (追記)
    .NET Framework 4.6以降ではなく、.NET Framework 2.0以降ということです。
    お詫びし、訂正いたします。


    ★良い回答には質問者は回答済みマークを、閲覧者は投票を!




    • 編集済み trapemiyaModerator 2018年5月15日 9:56 追記
    • 回答としてマーク sasatomo 2018年5月16日 2:15
    • 回答としてマークされていない sasatomo 2018年5月16日 3:37
    • 回答としてマーク sasatomo 2018年5月16日 4:12
    2018年5月15日 6:49
    モデレータ
  • ありがとうございました。バージョンは2017ですので
    purchaseRecordDataTableBindingSource.Filter = "商品ID = " + Program.Itemid; で出来ました。

    静的な変数経由で値を渡すのはあまり良くないとのことでしたので、引き続きアドバイスをいただいた箇所を修正して
    みようと思っております。
    またご質問させていただくかもしれませんが、よろしくお願い致します。
    差し当たり御礼を申し上げます。

    丁寧な説明をありがとうございます。

    2018年5月15日 8:33
  • 細かいことで本筋からは外れますが、2017だと以下のようにも書けるということです。

    purchaseRecordDataTableBindingSource.Filter = $"商品ID = {Program.Itemid}";

    上記の$を使った書き方はC# 6で追加された機能で、string interpolation(文字列補間)と呼ばれますが、.NET Framework 2.0以降で動くようです。訂正とお詫びをいたします。

    string interpolation
    http://ufcpp.net/study/csharp/cheatsheet/listfxlangversion/


    ★良い回答には質問者は回答済みマークを、閲覧者は投票を!

    • 回答としてマーク sasatomo 2018年5月16日 2:16
    2018年5月15日 9:54
    モデレータ
  • BindingSourceを利用したWindowsフォームでのフィルター操作についてさん
    こんにちは、フォーラム オペレーターの立花です。
    MSDN フォーラムへご投稿くださいましてありがとうございます。

    trapemiya さんから頂いた回答はお役に立ちましたでしょうか。
    同じ問題であとから参照した方が、素早く情報を取得できるように、
    参考になった回答には、その投稿に [回答としてマーク] をご設定ください。

    お手数ですが、ご協力の程、どうぞよろしくお願いいたします。

    フォーラム利用時の注意点のお知らせです。
    ※初めてご投稿された方を対象にお知らせしています。

    ご利用の際は、下記内容をお守りいただきますと
    情報が寄せられやすくなりますので、ぜひご一読ください。
    フォーラムでご質問頂くにあたっての注意点
    フォーラムのご利用方法(質問の投稿)について
    フォーラムへの回答に関するガイドラインおよびフォーラム運営について(再掲)
    ご意見、ご要望はこちらのフォーラムまで。
    各種設定方法はフォーラム内を [かんたん フォーラム ガイド] で検索してみてください。


    参考になった投稿には回答としてマークの設定にご協力ください
    MSDN/TechNet Community Support 立花楓

    • 回答としてマーク sasatomo 2018年5月16日 2:25
    2018年5月16日 2:01
    モデレータ
  • アドバイスをありがとうございました。

    purchaseRecordDataTableBindingSource.Filter = $"商品ID = {Program.Itemid}";でも
    結果が出ました。ありがとうございました。

    また、アドバイスに従って作成し直してみようと思い、

    PurchaseRecordForm prForm =
    new PurchaseRecordForm(Convert.ToString(dgv.CurrentRow.Cells[1].Value));

    書き直して
    フォームBのコンストラクタの引数として渡してみましたが
    PurchaseRecordFormの部分に赤波線がつきエラーになりました。

    また、Filterで絞らず、Fillメソッドの引数としてthis.purchaseRecordTableAdapter.Fill(this.purchaseRecordDataSet.PurchaseRecordDataTable, 商品ID);と書いてみましたが、
    商品
    IDの部分に赤い波線がついてエラーになりました。
    PurchaseRecordDataTableには確かに商品IDはあります。)

    原因としてはどんな可能性がありますでしょうか。
    どのあたりを修正する必要があるかアドバイスを頂けたらと思っております。
    不慣れなことで大変恐れ入りますがよろしくお願い致します。

    2018年5月16日 4:15
  • PurchaseRecordForm prForm =

    new PurchaseRecordForm(Convert.ToString(dgv.CurrentRow.Cells[1].Value));
    書き直して
    フォームBのコンストラクタの引数として渡してみましたが
    PurchaseRecordFormの部分に赤波線がつきエラーになりました。

    引数付きのコンストラクタがPurchaseRecordFormに定義されていないからでしょう。
    以下を参考にして、
    PurchaseRecordFormに引数付きのコンストラクタを定義してみて下さい。

    (参考)
    コンストラクタ
    http://www.kisoplus.com/kihon/const.html

    また、Filterで絞らず、Fillメソッドの引数としてthis.purchaseRecordTableAdapter.Fill(this.purchaseRecordDataSet.PurchaseRecordDataTable, 商品ID);と書いてみましたが、

    商品IDの部分に赤い波線がついてエラーになりました。
    PurchaseRecordDataTableには確かに商品IDはあります。)

    前述した通り、TableAdapterを作成し直す必要があります。既存のpurchaseRecordTableAdapterを右クリックして「構成」を選び、表示されたSQLのselect文に、whereを以下のように追加してみて下さい。
    select
    ・・・
    from PurchaseRecordDataTable
    where 商品ID = @商品ID

    ちなみに@を付けるとパラメータの意味になります。上記では@商品IDとしてわかりやすいパラメータ名にしましたが、名前は何でも構いません。例えば、@商品あいでぃ とかでも良いです。しかし、わかりやすいので一般的には列名とパラメータ名は合わせます。

    さて、このスレッドのタイトルと、上記の質問内容は合わなくなってきています。上記のアドバイスで追加のご質問があれば、新たにスレッドを立ててご質問下さい。よろしくお願いいたします。


    ★良い回答には質問者は回答済みマークを、閲覧者は投票を!

    2018年5月16日 4:49
    モデレータ
  • ありがとうございます。

    引き続き別のスレッドにてご質問させていただきます。
    お手数をおかけしますがよろしくお願い致します。
    2018年5月16日 5:40