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

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

ただいまの
回答率

90.11%

OnRowDataBoundでDropDownListの値を編集したい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 393
退会済みユーザー

退会済みユーザー

前提・実現したいこと

・DBで取得した値をDropDownListで表示

困っていること

・DataTableの値を編集した後にうまく表示されない

処理の流れ

(Page_Load)
1.DBからデータを取得
2.画面表示用にDataTableを作成

DataTable userInfo = new DabaTable(); //ユーザー情報
DataTable jobInfo = new DataTable();  //仕事情報→この中身をドロップダウンにしたい

//DBからデータを取得してuserInfo, jobInfoに入れる
//userInfoには名前と誕生日、jobInfoには職業名と~~仕事区分~~が入ります→IDが入ります
//(取得処理の内容は省略)

//画面表示用
DataRow dr;
  table.Columns.Add("Name", typeof(string));
  table.Columns.Add("Birthday", typeof(string));
  table.Columns.Add("Job", typeof(ListItem[]));

  foreach (DataRow row in userInfo.Rows)
  {
     dr = table.NewRow();
     dr["Name"] = row["名前"];
     dr["Birthday"] = row["誕生日"];
     dr["Job"] = null; //あとでデータを入れる
     table.Rows.Add(dr);
  }

this.UserInfoGridView.DataSource = table;
this.UserInfoGridView.DataBind();

(画面側)
1.表示

<asp:GridView ID="UserInfoGridView" runat="server" AutoGenerateColumns="False" OnRowDataBound="Grid_RowDataBound">
  <Columns>
      <asp:BoundField HeaderStyle-Width="300" DataField="Name" HeaderText="名前"></asp:BoundField>
      <asp:BoundField HeaderStyle-Width="300" DataField="Birthday" HeaderText="誕生日"></asp:BoundField>
      <asp:templatefield HeaderStyle-Width="300" HeaderText="仕事" >
        <itemtemplate>
          <asp:DropDownList ID="Job" runat="server" AutoPostBack="true"></asp:DropDownList>
       </itemtemplate>
      </asp:templatefield>
    </Columns>
</asp:GridView>

 
(OnRowDataBoundのとき)

protected void Grid_RowDataBound(object sender, GridViewRowEventArgs e)
{
  if (e.Row.RowType == DataControlRowType.DataRow)
  {
     int cnt = jobInfo.Rows.Count;
     ListItem[] list = new ListItem[cnt];
     var num = 0;
     foreach (DataRow jobRow in jobInfo.Rows)
     {
    list[num] = new ListItem { Text = jobRow.ItemArray[0].ToString(), Value = jobRow.ItemArray[1].ToString() };
       num++;
     }
      //ListItem[]の入れ方がこれでいいのかがわからない
      int tmp = e.Row.DataItemIndex;
      table.Rows[tmp][2] = list;

      var jobList = e.Row.FindControl("Job") as DropDownList;
      jobList.DataSource = table;
      //"Text"や"Value"を入れると「Textという名前のプロパティは含まれません」とエラーになる。。
      jobList.DataTextField = "Job";
      jobList.DataValueField = "Job";
      jobList.DataBind();
  }
}

結果

ドロップダウン自体は表示されますが、System.Web.UI.WebControls.ListItem[]という値がドロップダウンに表示されます。タスケテクダサイ。。

追記

DropDownListには職業名の一覧が入ります。
登録されたユーザーの職業を選択するイメージです。

DBデータ
ユーザテーブル
カラム:ID、名前、誕生日、仕事ID

仕事テーブル
カラム:ID、職業名、区分
jobInfoにはユーザテーブル.仕事ID=仕事テーブル.IDで検索したデータが入っています。
jobInfoには仕事テーブルに登録されている全職業名が入ります

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • 退会済みユーザー

    退会済みユーザー

    2019/04/10 15:29

    Visual Studioは2017 Version 15.7.3で、.NETはVersion4.7.03190で、DBはOracleです。

    DropDownListについては質問の一番下に追記しました。

    キャンセル

  • SurferOnWww

    2019/04/10 16:25

    「ユーザテーブル」の「仕事ID」が「仕事テーブル」の当該「ID」を指しているのですよね? 

    そして、Oracle だそうですが ODP.NET は使えますか? 以下の記事のように、それと SqlDataSource を組み合わせて使えますか? 使えれば、上に紹介した記事の応用でできると思うのですが。

    https://stackoverflow.com/questions/40909461/asp-net-c-sharp-sqldatasource-and-oracle-the-network-path-was-not-found

    キャンセル

  • SurferOnWww

    2019/04/10 16:34

    「OnRowDataBoundでDropDownListの値を編集したい」ということですが、見当違いの方向にはまり込んで迷走しているように思えます。紹介した記事 http://surferonwww.info/BlogEngine/post/2015/10/23/dropdpwnlist-handling-null-in-database.aspx をよく読んでください。これがやりたいことと異なる場合は、どこがどう異なるのか書いてください。

    キャンセル

回答 1

checkベストアンサー

+1

上の質問に対するコメントに返事がないので、ODP.NET + SqlDataSource が質問者さんの環境で使えるのかどうか不明ですが、使えるのであれば以下の記事の応用で簡単に実現できると思います。

DropDownList での NULL の処置
http://surferonwww.info/BlogEngine/post/2015/10/23/dropdpwnlist-handling-null-in-database.aspx

これが絶対的にお勧めです。ODP.NET + SqlDataSource が使えないということであれば、使えるように環境を整備すべきです。

もし、どうしても使えないということであれば・・・

Oracle DB より必要な DataTable は取得できているようですので、取得するためのコードをビジネスロジックとしてまとめ、ObjectDataSource 経由で GridView, DropDownList にバインドするのがお勧めです。

具体例は以下の通りです。

まず、ビジネスロジックを格納するクラスファイルを追加し、その中に DB より必要なデータを取得して DataTable を生成して返すメソッドのコードを書きます。

コードは以下のような感じです。DB は持ってないので、代わりに、質問の情報をベースにコードで DataTable を組み立てています。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;

/// <summary>
/// UserAndJobInfo の概要の説明です
/// </summary>
public class UserAndJobInfo
{
    public UserAndJobInfo()
    {
        //
        // TODO: コンストラクター ロジックをここに追加します
        //
    }

    public DataTable GetUserInfo()
    {
        DataTable table = new DataTable();
        table.Columns.Add(new DataColumn("Id", typeof(int)));
        table.Columns.Add(new DataColumn("Name", typeof(string)));
        table.Columns.Add(new DataColumn("Birthday", typeof(string)));
        table.Columns.Add(new DataColumn("JobId", typeof(int)));

        for (int i = 0; i < 5; i++)
        {
            DataRow row = table.NewRow();
            row["Id"] = i + 1;
            row["Name"] = "名前-" + (i + 1).ToString();
            row["Birthday"] = "1990/1/" + (i + 1).ToString();
            row["JobId"] = 5 - i;
            table.Rows.Add(row);
        }

        return table;
    }

    public DataTable GetJobInfo()
    {
        DataTable table = new DataTable();
        table.Columns.Add(new DataColumn("Id", typeof(int)));
        table.Columns.Add(new DataColumn("JobName", typeof(string)));
        table.Columns.Add(new DataColumn("Class", typeof(string)));

        for (int i = 0; i < 5; i++)
        {
            DataRow row = table.NewRow();
            row["Id"] = i + 1;
            row["JobName"] = "職業名-" + (i + 1).ToString();
            row["Class"] = "区分" + (i + 1).ToString();
            table.Rows.Add(row);
        }
        return table;
    }
}


.aspx のコードは以下のようになります。(.aspx.cs のコードは自動生成されたまま手を加えませんので割愛)

<%@ Page Language="C#" AutoEventWireup="true" 
    CodeFile="0067-DropDownListInGridView.aspx.cs" 
    Inherits="_0067_DropDownListInGridView" %>

<!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:ObjectDataSource ID="ObjectDataSource1" 
            runat="server" 
            SelectMethod="GetUserInfo" 
            TypeName="UserAndJobInfo">
        </asp:ObjectDataSource>

        <asp:ObjectDataSource ID="ObjectDataSource2" 
            runat="server" 
            SelectMethod="GetJobInfo" 
            TypeName="UserAndJobInfo">
        </asp:ObjectDataSource>

        <asp:GridView ID="GridView1" runat="server" 
            AutoGenerateColumns="False" 
            DataSourceID="ObjectDataSource1">
            <Columns>
                <asp:BoundField DataField="Id" HeaderText="ID" />
                <asp:BoundField DataField="Name" HeaderText="名前" />
                <asp:BoundField DataField="Birthday" HeaderText="誕生日" />
                <asp:BoundField DataField="JobId" HeaderText="仕事ID" />
                <asp:TemplateField HeaderText="職業名">
                    <ItemTemplate>
                        <asp:DropDownList ID="DropDownList1" 
                            runat="server" 
                            DataSourceID="ObjectDataSource2" 
                            DataTextField="JobName" 
                            DataValueField="Id"
                            SelectedValue='<%# Bind("JobId") %>'>
                        </asp:DropDownList>
                    </ItemTemplate>
                </asp:TemplateField>
            </Columns>
        </asp:GridView>
    </div>
    </form>
</body>
</html>

実行結果は以下の通りです。

イメージ説明

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/11 15:49

    回答が遅くなり申し訳ありません。
    ODP.NET + SqlDataSourceが使えない環境で。。。ですが、上記の方法で解決できました。ありがとうございました。

    キャンセル

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

  • ただいまの回答率 90.11%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る