質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
.NET Framework 4.0

Microsoft Windows用のソフトウェア開発環境/実行環境である .NET Frameworkの4番目のメジャーバージョンです。

ASP.NET

ASP.NETは動的なWebサイトやWebアプリケーション、そしてWebサービスを構築出来るようにする為、Microsoftによって開発されたウェブアプリケーション開発フレームワークです。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

Q&A

解決済

2回答

2941閲覧

動的に生成した表の中に動的にチェックボックスを配置したい

meesa

総合スコア12

.NET Framework 4.0

Microsoft Windows用のソフトウェア開発環境/実行環境である .NET Frameworkの4番目のメジャーバージョンです。

ASP.NET

ASP.NETは動的なWebサイトやWebアプリケーション、そしてWebサービスを構築出来るようにする為、Microsoftによって開発されたウェブアプリケーション開発フレームワークです。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

0グッド

0クリップ

投稿2017/12/26 11:52

編集2017/12/27 09:10

###前提・実現したいこと
ASP.NETでWEBアプリケーションを開発しています。
画面上に表を配置し、DBから取得した値を表示させようとしています。
セルには、DBから取得した値(数値0~9)や、「申請種類」という条件に応じて、
文字列か、チェックボックスを表示させたいです。

こういった場合に、なるべく可読性の高い、シンプルなソースで実現するための手法として、
どのような方法が考えられるか、教えていただきたいです。

自分で考えた方法は、

  1. GridViewを使用して表を生成
  2. チェックボックスを表示する可能性があるセルについては、TemplateFieldにし、

ラベルとチェックボックスを配置
0. RowDataBoundイベントで、ラベルとチェックボックスの表示非表示に切り替えを行う

というものです。

表示したい表のイメージは以下になります。
表示行数の想定は最大でも10行程度で、実際には2~5行がほとんどです。

・DBの値
|管理No.|ユーザー名|申請項目1|申請項目2|申請項目3|
|:--:|:--:|:--:|:--:|
|001|ユーザー1|1|0|1|
|001|ユーザー2|2|1|3|
|001|ユーザー3|1|2|2|
|002|ユーザー4|0|8|8|

・画面表示結果(管理No単位で画面表示)
管理No.:001
申請種類:申請1

ユーザー名申請項目1申請項目2申請項目3
ユーザー1申請不可
ユーザー2申請済
ユーザー3

※黒い四角はチェック済みのチェックボックスだと思ってください。

申請種類とDBの値の組み合わせ、その表示結果は、項目1の場合、
申請1かつ0:申請不可
申請2かつ0:チェックボックス(OFF)
申請1かつ1:チェックボックス(OFF)
申請2かつ1:申請対象外
申請1かつ2:チェックボックス(ON)
申請2かつ2:申請1申請中

項目2の場合、
申請1かつ0:申請不可
申請2かつ0:チェックボックス(OFF)
申請1かつ1:チェックボックス(OFF)
申請2かつ1:申請対象外(理由A)
申請1かつ2:チェックボックス(OFF)
申請2かつ2:申請対象外(理由B)
申請1かつ3:チェックボックス(ON)
申請2かつ3:申請1申請中

・・・のように、項目ごとに、DBが同じ値であっても意味が異なる場合があります。
また、DBの値7~9は、申請2の場合にチェックボックスを表示し、申請1では文字列を表示する
ために使用されています。(下記ソースでは省略しています)

###該当のソースコード

lang

1Private Sub GV_User_RowDataBound(sender As Object, e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GV_User.RowDataBound 2 3 If e.Row.RowType = DataControlRowType.DataRow Then 4 Select Case e.Row.Cells(2).Text 5 Case "0" 6          If DemType = 1 then 7 '申請種類1の場合、チェックボックスを表示せず、申請不可の文字を表示 8 e.Row.FindControl("lbl1").Visible = True 9 CType(e.Row.FindControl("lbl1"), Label).Text = "申請不可" 10 e.Row.FindControl("ckb1").Visible = False 11 Else 12 '申請1ではない場合、チェックボックス(オフ)を表示 13 e.Row.FindControl("lbl1").Visible = False 14 e.Row.FindControl("ckb1").Visible = True 15 CType(e.Row.FindControl("ckb1"),CheckBox).Checked = False 16 End If 17 Case "1" 18          If DemType = 1 then 19 'チェックボックス(オフ)を表示 20 e.Row.FindControl("lbl1").Visible = False 21 e.Row.FindControl("ckb1").Visible = True 22 CType(e.Row.FindControl("ckb1"),CheckBox).Checked = False 23 Else 24 '申請1ではない場合、チェックボックスを表示せず、申請対象外の文字を表示 25 e.Row.FindControl("lbl1").Visible = True 26 CType(e.Row.FindControl("lbl1"), Label).Text = "申請対象外" 27 e.Row.FindControl("ckb1").Visible = False 28 End If 29 Case "2" 30          If DemType = 1 then 31 '申請種類1の場合、チェックボックス(オン)を表示 32 e.Row.FindControl("lbl1").Visible = False 33 e.Row.FindControl("ckb1").Visible = True 34 CType(e.Row.FindControl("ckb1"),CheckBox).Checked = True 35 Else 36 '申請1ではない場合、チェックボックスを表示せず、申請1申請中の文字を表示 37 e.Row.FindControl("lbl1").Visible = True 38 CType(e.Row.FindControl("lbl1"), Label).Text = "申請1申請中" 39 e.Row.FindControl("ckb1").Visible = False 40 End If 41 42         '以下略(値7~9の場合の場合の分岐処理) 43 End Select 44 45 '以下略(申請項目数分繰り返し) 46 End If 47 End Sub

###試したこと
上記ソースはGridViewのRowDataBound処理の内容になります。
(実ソースそのままは出すことが出来ないため、簡略化しています)
一応、このソースで目的の動作をすることは確認できているのですが、うまく共通化や簡略化が
出来ず、RowDataBoundイベントが大変長くなってしまっています。(350行ほど)

また、上記表の列「申請項目」に該当するものが、全部で6列あります。
項目ごと分岐数や表示文字列が異なったりするため、共通関数にうまく落とし込めません。
そもそも、チェックボックスやラベルの表示/非表示を切り替える、という
やり方が、一般的なのかどうかもわかりません。

もっとスマートな書き方や、一般的にはこうするんじゃない?という情報があれば、
教えていただきたいです。

GridViewにもこだわりませんので、ご意見やアイディア、ヒントを伺えれば助かります。

###補足情報(言語/FW/ツール等のバージョンなど)
asp.net(VB)
.NetFramework 4.0
Visual Studio 2010

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/12/26 12:04

DataGridView? ASP.NET の話ですよね? 「実際のソースはSelect分岐が約10個あり、それがもう5項目分あります」とはどういうことですか? もっと具体的に書いてください。
meesa

2017/12/26 12:28

大変失礼しました。GridViewの間違いです。Select分岐については、質問内の表記を修正しました。分岐条件が約10個ある、という意味です。また、項目数は表の列数で、全部で6項目分同じような分岐でセル内の表示内容を修正する必要がありました。
退会済みユーザー

退会済みユーザー

2017/12/26 12:55 編集

それではエスパーではない自分には分かりません。「分岐条件が約10個」をもっと詳しく、ここに書いてあること以外は第三者は知り得ないということを理解していただいて、ここを読めば分かるように書いてください。データソースがどうなっているのかから分からないと少なくとも自分には何の提案もできません。
guest

回答2

0

ベストアンサー

せっかく説明していただいたのに何ですが、判定ロジックが理解できませんので、判定ロジックの改善案の提案はできません。(350 行を短くするための提案や判定ロジックのコードを読みやすくするための提案はできませんという意味です)

代わりに、もっと基本的な改善案、プレゼンテーション層、ビジネスロジック層、データ層という 3 層構造に分けることを提案します。

3 層構造がどういうものかについては以下の記事の図1を見てください。

第1回 ASP.NETによる3階層Webアプリ「ITブック」構築
http://www.atmarkit.co.jp/fdotnet/chushin/kaizowebui_01/kaizowebui01_01.html

今の質問者さんのコードは、判定ロジックが ASPX ページのコードビハインドに含まれている、即ち、プレゼンテーション層(ASPX ページ)とビジネスロジック層(判定ロジック)が一緒になっていて 2 層構造になっています。

これを 3 層構造にする、即ち、GridView の RowDataBound イベントのハンドラに判定ロジックを含めるのではなく、別にクラスファイルを作ってそれに含めるようにします。そうすれば、少なくとも ASPX ページのコードの可読性や全体の保守性はかなり上がると思います。

具体的には、クラスファイルに、DB から生データの取得 ⇒ それをベースに各列に何を表示するかを判定 ⇒ 判定結果を戻り値として返す・・・というメソッド(即ち、ビジネスロジック)を実装します。

メソッドの戻り値は、先の質問者さんのスレッド https://teratail.com/questions/101809 で私が例として書いた List<T> 型にするのが良いと思います。

T は例えば(あくまで例えばです)以下のようにし、Application1 ~ 6 には判定ロジックで生データを判定した結果("applied", "N/A", "check", "unckeck" など)を格納します。

public class Result { public string ControlNumber { get; set; } public string UserName { get; set; } public string Application1 { get; set; } public string Application2 { get; set; } public string Application3 { get; set; } public string Application4 { get; set; } public string Application5 { get; set; } public string Application6 { get; set; } }

ASPX ページには GridView と ObjectDataSource を実装し、クラスファイルに実装したメソッドを ObjectDataSource の SelectMethod に設定すれば、判定結果(上の例で言うと "applied", "N/A", "check", "unckeck")が表示できます。

ChackBox にする必要はなくて、結果を文字列として表示できれば良いのであればそれだけで済むはずです。

どうしても CheckBox と Label を切り替えて表示したいということであれば、GridView の RowDataBound イベントのハンドラで処置するなどもう一工夫必要ですが、ASPX ページのコードの可読性は格段に上がるはずです。

【追記】

サンプルを作ったのでアップしておきます。Result クラスは上のものから簡略化しました。.aspx のコードで、GridView1 が文字列で表示、GridView2 が CheckBox と Label を切り替えて表示するようにしています。

ビジネスロジック

using System; using System.Collections.Generic; using System.Linq; using System.Web; public class Result { public string Name { get; set; } public string App1 { get; set; } public string App2 { get; set; } public string App3 { get; set; } } public class BusinessLogic { public List<Result> GetResults() { List<Result> results = new List<Result>() { new Result() { Name = "ユーザー1", App1 = "チェック未", App2 = "申請不可", App3 = "チェック未" }, new Result() { Name = "ユーザー2", App1 = "チェック済", App2 = "チェック未", App3 = "申請済" }, new Result() { Name = "ユーザー3", App1 = "チェック未", App2 = "チェック済", App3 = "チェック済" } }; return results; } }

.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="0022-GridViewCheckBox.aspx.cs" Inherits="_0022_GridViewCheckBox" %> <!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"> <asp:ObjectDataSource ID="ObjectDataSource1" runat="server" SelectMethod="GetResults" TypeName="BusinessLogic"> </asp:ObjectDataSource> <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataSourceID="ObjectDataSource1"> <Columns> <asp:BoundField DataField="Name" HeaderText="ユーザー名" /> <asp:BoundField DataField="App1" HeaderText="申請項目1" /> <asp:BoundField DataField="App2" HeaderText="申請項目2" /> <asp:BoundField DataField="App3" HeaderText="申請項目3" /> </Columns> </asp:GridView> <asp:GridView ID="GridView2" runat="server" AutoGenerateColumns="False" DataSourceID="ObjectDataSource1"> <Columns> <asp:BoundField DataField="Name" HeaderText="ユーザー名" /> <asp:TemplateField HeaderText="申請項目1"> <ItemTemplate> <asp:CheckBox ID="CheckBox1" runat="server" Visible='<%# CheckBoxVisible((string)Eval("App1")) %>' Checked='<%# IsChecked((string)Eval("App1")) %>' /> <asp:Label ID="Label1" runat="server" Text='<%# Eval("App1") %>' Visible='<%# LabelVisible((string)Eval("App1")) %>'> </asp:Label> </ItemTemplate> </asp:TemplateField> <asp:TemplateField HeaderText="申請項目2"> <ItemTemplate> <asp:CheckBox ID="CheckBox2" runat="server" Visible='<%# CheckBoxVisible((string)Eval("App2")) %>' Checked='<%# IsChecked((string)Eval("App2")) %>' /> <asp:Label ID="Label2" runat="server" Text='<%# Eval("App2") %>' Visible='<%# LabelVisible((string)Eval("App2")) %>'> </asp:Label> </ItemTemplate> </asp:TemplateField> <asp:TemplateField HeaderText="申請項目3"> <ItemTemplate> <asp:CheckBox ID="CheckBox3" runat="server" Visible='<%# CheckBoxVisible((string)Eval("App3")) %>' Checked='<%# IsChecked((string)Eval("App3")) %>' /> <asp:Label ID="Label3" runat="server" Text='<%# Eval("App3") %>' Visible='<%# LabelVisible((string)Eval("App3")) %>'> </asp:Label> </ItemTemplate> </asp:TemplateField> </Columns> </asp:GridView> </form> </body> </html>

.aspx.cs

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; public partial class _0022_GridViewCheckBox : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { } protected bool LabelVisible(string str) { if (str == "チェック未" || str == "チェック済") { return false; } return true; } protected bool CheckBoxVisible(string str) { if (str == "チェック未" || str == "チェック済") { return true; } return false; } protected bool IsChecked(string str) { if (str == "チェック未") { return false; } if (str == "チェック済") { return true; } return false; } }

投稿2017/12/28 03:29

編集2017/12/28 05:38
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

meesa

2017/12/28 05:54

判定はビジネスロジック化して分離、ラベルとチェックボックスの表示切替は小さな共通化メソッド化と、SurferOnWwwさんとkenshirouさんから頂いた回答を元に実装することに致しました。 サンプルもご提示いただいたので、SurferOnWwwさんをベストアンサーとさせていただきました。 お二人ともありがとうございました。
guest

0

これは直接の回答ではありません。

6項目分で異なる分岐があるのであれば、
それはコードとして書かなければなりません。

ただし、どちらかというと方法論になりますが、

チェックボックスを出すか、テキスト(ラベルを出すか)

という処理であれば、共通化できるのではないかと思います。

例えば、共通化のメソッドの引数として、
・ラベル・チェックボックスの識別子("1"なら"lbl1"と"chk1"が対象、等)
・チェックボックス表示か、ラベル表示かの区分
(例えばBooleanで、Trueならチェックボックス表示、Falseならラベル表示、等)
・チェックボックス表示の場合、デフォルトのチェック(Boolean)
・ラベル表示の場合のラベル内容(String)

を用意し、各分岐で上記メソッドを呼び出して対応すれば、分岐処理の部分がスッキリする
(少なくとも、Case文内の3行は1行になる)のではないかと思いますが、
如何でしょうか?

投稿2017/12/27 07:50

kenshirou

総合スコア772

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

meesa

2017/12/27 09:40

おっしゃるとおりの方法で共通化することで、一つ一つの分岐の中の記述はかなりスッキリさせることが出来そうです! 早速試してみます。
kenshirou

2017/12/28 00:40

質問内容が編集されたので、以下の提案がうまく適用できるかどうか不明ですが、 もし、申請種類とDB値でその対処法が決まるのであれば、申請種類とDB値に応じた情報 (例えば上記で説明した共通化メソッドの引数のような情報)を、何らかのテーブル (DBで管理してもいいし、外部設定ファイルを用意してもいいです)に用意すれば、 このテーブルを参照することにより、Case文の分岐も不要になります。 もし、この方法が使えるのであれば、メンテナンス性も良くなると思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問