QA@IT

checkboxと一致しないgridviewの行を表示する方法

9013 PV

最近、勉強をし始めたばかりのプログラミング初心者です。

開発環境:Visual Studio 2015
データソース:SQL Server localDB

《テーブル詳細》

CREATE TABLE [dbo].[menu] (
    [ID]      INT            IDENTITY (1, 1) NOT NULL,
    [name] NVARCHAR (50) NOT NULL,
    [price]       INT         NOT NULL,
    [f1]       BIT             NULL,
    [f2]       BIT             NULL,
    [f3]       BIT            NULL,

    PRIMARY KEY CLUSTERED ([ID] ASC),
);

《Visual Studio画面》
ckb1□ ckb2□ ckb3□
=====gridview=====

===============
[検索]

《やりたいこと》
ckb1をチェックして検索をおすと、ckb1のものを"含まない"データをGridviewで表示させたいです。
ckb1とf1,ckbとf2,ckb3とf3を同じ項目として一致させ
ckb1つまり「f1がtrueになっているデータ」を排除したものを表示させたいです。
もしckb1とckb2がどちらもtrueになっていたら、
「f1のみ・f1とf2・f2のみ」がtrueになっているデータを排除させたいです。

※修正※ システムの目的として、[f1][f2][f3]についてtrueでもfalseでもデータとして登録できるようにしておきたいので、NOT NULLではなくNULLに再度修正させていただきました。やはり、このBITをNULLにするのは、まずいのでしょうか?

HTMLはこのようになっております。

<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="ssa.aspx.vb" Inherits="App.ssa" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
     <asp:Label ID="Label2" runat="server" Font-Names="メイリオ" Font-Size="Large" Text="●料理名"></asp:Label>
        <br />
        <asp:TextBox ID="TextBox1" runat="server" Width="321px"></asp:TextBox>
        <br />
        <asp:Label ID="Label3" runat="server" Font-Names="メイリオ" Font-Size="Large" Text="●好きなものは"></asp:Label>
        <br />
        <asp:CheckBox ID="CheckBox1" runat="server" Font-Names="メイリオ" Font-Size="Large" Text="鶏" />
        <asp:CheckBox ID="CheckBox2" runat="server" Font-Names="メイリオ" Font-Size="Large" Text="牛" />
        <asp:CheckBox ID="CheckBox3" runat="server" Font-Names="メイリオ" Font-Size="Large" Text="豚" />
        <br />
        <asp:Button ID="Button3" runat="server" Font-Names="メイリオ" Font-Size="Large" Text="検索" />
        <br />
        <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" BackColor="White" BorderColor="#336666" BorderStyle="Double" BorderWidth="3px" CellPadding="4" DataKeyNames=ID" DataSourceID="SqlDataSource1" GridLines="Horizontal" AllowPaging="True">
            <Columns>
                <asp:HyperLinkField DataNavigateUrlFields="cookID" DataNavigateUrlFormatString="result.aspx?ID={0}" HeaderText="詳細" NavigateUrl="~/result.aspx" Text="詳細" />
                <asp:BoundField DataField="name_jp" HeaderText="料理名" SortExpression="name" />
                <asp:BoundField DataField="price" HeaderText="値段" SortExpression="price" />
                <asp:CheckBoxField DataField="f1" HeaderText="鶏" SortExpression="f1" />
                <asp:CheckBoxField DataField="f2" HeaderText="牛" SortExpression="f2" />
                <asp:CheckBoxField DataField="f3" HeaderText="豚" SortExpression="f3" />
            </Columns>
            <EmptyDataTemplate>
                <asp:Label ID="Label4" runat="server" Text="該当するデータがありません。&lt;br&gt;抽出条件を指定してから「検索」ボタンをクリックしてください。"></asp:Label>
            </EmptyDataTemplate>
            <FooterStyle BackColor="White" ForeColor="#333333" />
            <HeaderStyle BackColor="#336666" Font-Bold="True" ForeColor="White" />
            <PagerStyle BackColor="#336666" ForeColor="White" HorizontalAlign="Center" />
            <RowStyle BackColor="White" ForeColor="#333333" />
            <SelectedRowStyle BackColor="#339966" Font-Bold="True" ForeColor="White" />
            <SortedAscendingCellStyle BackColor="#F7F7F7" />
            <SortedAscendingHeaderStyle BackColor="#487575" />
            <SortedDescendingCellStyle BackColor="#E5E5E5" />
            <SortedDescendingHeaderStyle BackColor="#275353" />
        </asp:GridView>
        <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:ConnectionString2 %>" SelectCommand="SELECT ID, name,price, f1, f2, f3 FROM menu2 WHERE (name LIKE '%' + name + '%')">
            <SelectParameters>
        <asp:ControlParameter ControlID="TextBox1" DefaultValue="%" Name="name" PropertyName="Text" Type="String" />
            </SelectParameters>
        </asp:SqlDataSource>
        <br />
         <asp:Button ID="Button1" runat="server" Text="最初に戻る" Font-Names="メイリオ" Font-Size="Large" />

    </div>
    </form>
</body>
</html>

また.aspはこのようになっております。


Public Class seachlist
    Inherits System.Web.UI.Page
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    End Sub

    Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        GridView1.DataSourceID = ""
        GridView1.DataSource = SqlDataSource1
        GridView1.DataBind()
    End Sub

    Protected Sub GridView1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles GridView1.SelectedIndexChanged
    End Sub

    Protected Sub SqlDataSource1_Selecting(sender As Object, e As SqlDataSourceSelectingEventArgs) Handles SqlDataSource1.Selecting
    End Sub
End Class

SurferOnWww様、大変申し訳ございません。
無視をしていたわけではなく、勘違いをしておりました。
完全というと、こういうことでしょうか。
本当に、分かっておらず…
質問に答えてくださっているのに、SurferOnWww様に
不快な気持ちを抱かせてしまい
申し訳ございません。

  • 開発環境 (OS, .NET, Visual Studio のバージョンなど) を書いてください。 -
  • あと、データーソースは何ですか? SQL Server とかなら検索先のテーブル詳細を書いてください。 -
  • 「やりたいこと」に対して実際どうなってしまうのかも書いた方がいいかと思います。あとWebFormsだと思いますが、Page_Loadで Postbackのチェックは行ってますか?(検索ボタン押した時もチェックボックスの初期化などされたりしてませんか?) -
  • 実際どうなっているか、というと何も出来ていないというのが答えです…。if文で「 if checkbox1.checked then …  」からが何もかけておらず、どうすればいいのか詰まってしまっています。また、検索ボタンを押した後も、チェックボックスの初期化はされていないことが確認できています。コメントありがとうございました。 -
  • 条件を付けず全レコード一覧表示なら自力でできるのですか? 「何もできてない」のでは話にならないので、そこまではできる知識・スキルは自分で勉強して身につけてください。その先の条件付き抽出の話はそれからにお願いします。 -
  • 次に、質問者さんの条件を満たすクエリは SELECT ID, name, price FROM menu WHERE f1 <> ckb1 OR f2 <> ckb2 OR f3 <> ckb3 でいいのか確認してください。違うのであれば書き直したクエリを連絡ください。 -
  • 全レコード表示は出来ております。しかしそこから、チェックボックスでの条件付き抽出ができない状態にいます。また、クエリについても確認させていただきます。 -
  • そのコードを貼ってください。 -
  • GridviewにSqlDataSourceを結び付け、カスタムSQLステートメントの定義に、SurferOnWww様のものを入れ込みました。パラメーターにて「名前:f1」「パラメーターソース:Control」「値:ckb1」と設定しました。しかし、実際にデバックすると、CheckBox1をチェックし、検索ボタンをかけてもGridviewの表示は依然全コードのみが一覧表示されていました。 -
  • 検索ボタンには
    GridView1.DataSourceID = ""
    GridView1.DataSource = SqlDataSource1
    GridView1.DataBind()
    を書いております。
    -
  • SELECT ID, name, price, f1, f2, f3 FROM menu WHERE (name LIKE '%' + @name + '%') OR (f1 <> @f1) OR (f2 <> @f2) OR (f3 <> @f3) と書いています。 -
  • (name LIKE '%' + @name + '%')は、同ページ内にTextboxを配置し、そこに入れられた文字列を含むコードを抽出するようにしています。こちらの方は抽出が可能になっています。 -
  • 断片的にコメント欄に書かないで、解答欄に全レコード抽出の場合の完全なコードを追記してください。完全と言っても、基本的な動作に関係ないスタイルなどは削除してください。 -
  • 完全なとお願いしたはずですが、完全でないですよね? SqlDataSource を使っているのでは? そちらも重要なんですが、そのコードは? あと、「動作に関係ないスタイルなどは削除してください」とお願いしたはずですが。 -
  • 話が通じないようですね。SqlDataSource に設定したクエリを聞いているわけではなく、SqlDataSource 全体のコードが知りたいのですけど・・・ 「動作に関係ないスタイルなどは削除してください」とお願いしたことも無視しないで、SqlDataSource のコードを追加するのと一緒に上の質問のコード全体を書き直してください。 -
  • どこが関係あってどこが関係ないのか不安であれば、編集できるので、一旦全部貼ってみては。途中からではなく最初から最後まで。ただし個人情報や秘密の情報は貼らないように気をつけてください(履歴残るので)。その上で色とか動作に関係ないと思われるところを編集で削ってみては(削り中ならコメント残してくれればわかるんで)。 -
  • flied_onion様、コメントありがとうございます。SurferOnWww様にも同様の指摘を頂きましたので、再度質問を修正し、挙げ直しました。一応、Gridviewのデザイン関係のコードなど不必要と思われるコードは消して、全てを載せたつもりなのですが、これでもまだどこか間違っているような気がします。すみません…。また履歴が残ってしまうのは知りませんでした。気を付けます。 -
  • > システムの目的として、[f1][f2][f3]についてtrueでもfalseでもデータとして登録できるようにしておきたいので、NOT NULLではなくNULLに再度修正させていただきました。 ← 何故そんな必要があるのか、意味が分かりません。例えば f1 が NULL だった場合、WHERE (f1 <> @f1) OR ... の (f1 <> @f1) は unknown になるはずですが -
  • コードは依然として完全じゃないですよ。Button も ChechBox もない。 -
  • イベントハンドラ Button1_Click の中のコードはメチャクチャです。それを削除して、DB の f1, f2, f3 に NULL がない状態で試してどうなりますか? 期待通りになりませんか? 期待撮りでない場合、そのようなことを期待したが結果はどうなってしまうのか詳しく書いてください。 -
  • WHERE (f1 <> @f1) OR (f2 <> @f2) OR (f3 <> @f3) で質問者さんの求める条件に合うかどうかは自分は分かりません。《やりたいこと》が自分には意味不明ですので。WHERE 句は質問者さんの方せ自分の責任で考えて書いてください。 -
  • 申し訳ございません。自分で考えて一度すべてやり直してみます。 -
  • VB.NET側はグリッドのあるページのソースはそれで全部なのでしょうが、HTML側が完全じゃないです。ページ全体のソースを見せてください。(無駄と思われる部分は全部提示したあとで編集で削りましょう。) 具体的には前半のHTMLが全然ないですよね(たとえば`</form>`と対になる開始場所がないですよね)。 -
  • flied_onion様、ありがとうございます。Gridviewばかり考えてしまい、全体という言葉の意味を認識できていませんでした。修正させていただきました。 -
  • `CodeBehind="ssa.aspx.vb" Inherits="App.ssa"`なので、提示されてるVB.NETのソースはこのGridviewのものではないですね。VB.NETのソース(Classのソース)は ssa.aspx.vb ファイルのものではないですよね? Class ssaの内容がssa.aspx.vbにあるとおもいますのでそのコードも提示した方がいいでしょう。 -
  • というか、それが「何も出来ていない」原因じゃないですかね(関係ないVB.NETソースを編集してる)
    VS2015でどうなってるか覚えてないですが、HTMLの画面で右クリックして「コードの表示」とかで対応するVB.NETのソース開かれませんかね(違ったらすいません)。開いてssaクラスがいればそれがそのページのVB.NETコードです。
    -
  • > `CodeBehind="ssa.aspx.vb" Inherits="App.ssa"`なので ← App は名前空間名、ssa はコードビハインドに定義されているクラス名で、そのあたりの不整合はないと思います。> flied_onion さん -
  • 質問者さん> 上のような疑問が生じないように完全なコードを貼るように、何度も何度もお願いしているのですよ。お願いしたことはきちんとやってもらえないとフォローしきれません。 -
  • 上の質問者さんのコメントで「全レコード表示は出来ております」とありましたが、それは今 2/14 10:54 現在質問にアップされているコートでできているという理解で良いですか? -
  • ssaがコードビハインドのクラス名なのに、出ているVB.NETのコードのクラス名がseachlist なので合ってないない気がすると思ったんですが、これで大丈夫なんでしたっけ?(それともseachlistはコードビハインドのコードとして提示されたものではない?) > SurferOnWwwさん。 -
  • そうですね、失礼しました。質問者さんによると、全件抽出や name 条件で抽出は出来ているそうですので、ssa クラスは別に存在するのだと思います。 -

回答

コメント欄でやり取りしていても、書ける文字数の制限もあって空回りが止まらないような気がしますので、一旦リセットしてこの回答から話を進めたいと思います。

質問者さんのコメントを見ると、現状は、SqlDataSource と GridView を使って、

(1) 条件なし、即ち SELECT ID, name, price, f1, f2, f3 FROM menu というクエリで全レコードの抽出と表示はできている。

(2) クエリに WHERE (name LIKE '%' + @name + '%') を追加して TextBox からの入力で条件を付けてレコードを抽出して表示することもできている。

(3) さらに WHERE 句に OR (f1 <> @f1) OR (f2 <> @f2) OR (f3 <> @f3) の条件を追加し、CheckBox を 3 つ追加し、それぞれの Checked プロパティの値をパラメータ @f1, @f2, @f3 に代入するようにしたところ、期待に反して全レコードが抽出されてしまう。

そして、現在の問題は、(3) で、CheckBox のチェックに応じて条件が絞られて特定のレコードだけが抽出・表示されると期待したが、期待に反して全レコードが抽出されてしまう。

・・・ということと理解しています。理解が違っていたら、どこがどう違うのか詳しく書いてください。

全レコードが抽出されてしまうのは WHERE 句全体の条件が true になるからです。条件を OR でつないでいるので条件のどれか一つでも true になれば WHERE 句全体の条件は true になります。

それが NG ということであれば、質問者さんが WHERE 句に設定した条件が、DB のレコードの実態と目的に合ってないということになります。

上にも書きましたが、質問に書いてある《やりたいこと》が自分には意味不明ですので、WHERE (f1 <> @f1) OR (f2 <> @f2) OR (f3 <> @f3) が質問者さんの求める条件に合うかどうかは自分は分かりません。

だから、「違うのであれば書き直したクエリを連絡ください。」とお願いしました。DB のレコードの実態と目的に沿って書き直してください。

編集 履歴 (0)
  • SurferOnWww様、本当にありがとうございます。
    (1)~(3)までのお話ですが、その通りでございます。私の手順が悪く何度も何度も開示する情報を間違えてしまい、加えて説明もうまく出来ていなかったので本当に伝わりにくかったと思います。申し訳ございませんでした。
    そういうことだったのですね。確かに、ORで繋げた結果を冷静になって考れば、全表示の未来が見えました。
    -
  • 「やりたいこと」というのは、SurferOnWww様の言葉をお借りすると「各CheckBoxのチェックに応じて《そのCheckBoxにチェックの入っていないレコード》という条件で絞られて、特定のレコードだけが抽出・表示されること」です。 -
  • 例:CheckBox1にチェックを入れて検索ボタンを押したとき、Gridviewには《f1のチェックが入っているレコード》を排除した残りのレコードを表示する -
  • その説明では自分は分からないので自分はクエリは書けません。その質問をするとまた空回りするのは間違いなさそうなので、質問者さんの方でよく考えて自分のやりたいことをクエリの形にしてください。それができればここの問題は解決すると思います。 -
  • CheckBox1 だけにチェックが入っていた場合 WHERE f1 = 0 だけでいいのか、それとも WHERE f1 = 0 AND f2 = 1 AND f3 = 1 とするのか? NULL の扱いはどうするのか? NULL か否かをチェックできるのは IS NULL または IS NOT NULL しかないがそれをクエリにどう入れ込むか? ・・・等々よく考えてクエリを作ってください。 -
  • SurferOnWww様、長い間私の相談にお付き合いいただき、本当にありがとうございました。私自身の伝え方不足で、何度も苛つかせてしまったと思います。申し訳ございませんでした。今、一度自分のやりたいことをノートにまとめて自分の中で整理をしています。SurferOnWww様からいただいたクエリの案ももとにして、自分で作成し、自分の望んだ動作がかなったとき、ここにまとめて書きたいと思います。 -
  • ありがとうございました。クエリについて、調べて考えて必ず実現させるようにします。 -
  • 時間がかかるようであればこのスレッドはクローズして、クエリの書き方の問題として新たに別のスレッドを立てて質問していただければと思います。今はもう単純に SQL Server の SELECT クエリの書き方の問題ですので、答えられる人が大勢いると思いますから。 -
  • SurferOnWww様、今まで多くのコメントを残していただき、ありがとうございました。いまだ複数条件クエリがうまく使えていないので、どうしても解決できなかった場合に別スレッドで質問したいと思います。 -

一度こちらに書いた追加の情報を
質問に「追加」ということで
書かせていただきました。
質問方法自体がよくわかっていませんでした。
教えて頂き、ありがとうございます。

編集 履歴 (1)
  • 質問者s何は回答欄に書かないで、追加情報などは質問欄に追記する形で書いてください。ここではそれが流儀のようですので、質問者さんに回答欄に書かれると訳が分からなくなってしまいます。 -
  • 今からでも遅くないので、上に書かれたことは回答欄に移動して、上には移動した旨書いていただければと思います。 -
  • f1 ~ f3 は NULL 可になってますが、NULL 不可にしないと破綻するのでは? そうでなければ NULL の時はどうするのですか? -
  • SELECT ID, name, price FROM menu WHERE f1 <> ckb1 OR f2 <> ckb2 OR f3 <> ckb3 でいいのですか? 違うのであれば書き直したクエリを連絡ください。 -
  • 今分かりました。これで「コメント」というもので返せているのでしょうか。SurferOnWwwさん、度々申し訳ございません。 -
  • 「新しいクエリ」からクエリを作成して、先程頂いたSELECT文を書き込み保存、それをvisual studioに入れてという流れでしょうか?クエリを~aspx.vbに入れ込む作業をしたことがないため、ただいま検索中です。 -
ウォッチ

この質問への回答やコメントをメールでお知らせします。