【ASP.NET】 WEBフォーム GridView上に複数のドロップダウンリストを配置・連動させる 

# 【Qiita初投稿】ASP.NETの記事を書きたいと思っています。
　仕事でWEBフォームを利用しており、今回GridView上に複数のドロップダウンリストを配置して連動させることが必要になりました。
　数時間ほど色々と調べて完成させることが出来たので、備忘録として実装例を紹介します。

## 実現したいこと
下図みたいな書籍名とその書籍を出版した会社名の一覧がある場合に、出版社名を選択すると
その出版社が出版した書籍の一覧がドロップダウンリストに設定される。

| 出版社     |書籍名　　　　　　　 | 
|:---------- |:------------------|
| 日経BP社   |アプリを作ろう! Android入門 | 
| 技術評論社  |Angular JSアプリケーションプログラミング | 
| 技術評論社  |サーブレット&JSPポケットリファレンス | 
| 技術評論社  |PHPライブラリ&サンプル実践活用 | 
| 翔泳社     | 10日でおぼえるJSP&サーブレット入門教室 | 
| 翔泳社     | JavaScript逆引きレシピ | 
| 秀和システム| PHPライブラリ&サンプル実践活用 | 

イメージ例）
![完成例.png](https://qiita-image-store.s3.amazonaws.com/0/285737/9d5889c7-062c-a725-220b-f35be597bea6.png)
⇨ 技術評論社を選択した場合、技術評論社が出版した書籍の一覧が表示される。

## 実装する上でのポイント（自分が躓いたところ）
・出版社のドロップダウンリストの値が変更されると、ポストバックを実行して書籍のドロップダウンリストを作成する。
・出版社ドロップダウンリストを変更した場合、同じ行の書籍ドロップダウンリストを編集する方法

## 実装
```C#:Book.cs
namespace WebApp2.Models
{
    using System;

    public partial class Book
    {

        public string Isbn { get; set; }

        public string Title { get; set; }

        public int Price { get; set; }

        public int PublishCd { get; set; }

        public DateTime Published { get; set; }

        public bool Cdrom { get; set; }

        public Book(string isbn, string title, int price, int publishCd, DateTime published, bool cdrom)
        {
            Isbn = isbn;
            Title = title;
            Price = price;
            PublishCd = publishCd;
            Published = Published;
            Cdrom = cdrom;
        }

    }
}
```

```C#:TEST001.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="TEST001.aspx.cs" Inherits="WebApp2.VIEWS.TEST001" %>

<!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:GridView ID="Grid" runat="server" AutoGenerateColumns="False" OnRowDataBound="Grid_RowDataBound">
                <Columns>
                    <asp:TemplateField HeaderText="No">
                        <ItemTemplate>
                            <asp:Label ID="lblNo" runat="server"></asp:Label>
                        </ItemTemplate>
                    </asp:TemplateField>
                    <asp:TemplateField HeaderText="出版社">
                        <ItemTemplate>
                             //AutoPostBack="True"にしてOnSelectedIndexChangedイベントを追加すること
                            <asp:DropDownList ID="ddlPublish" runat="server" Width="150px" AutoPostBack="True" OnSelectedIndexChanged="DDLPublish_SelectedIndexChanged">
                            </asp:DropDownList>
                        </ItemTemplate>
                    </asp:TemplateField>
                    <asp:TemplateField HeaderText="書籍">
                        <ItemTemplate>
                            <asp:DropDownList ID="ddlBook" runat="server" Width="500px">
                            </asp:DropDownList>
                        </ItemTemplate>
                    </asp:TemplateField>
                </Columns>
            </asp:GridView>
        </div>
    </form>
</body>
</html>
```

```C#:TEST001.aspx..cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using WebApp2.Models;

namespace WebApp2.VIEWS
{
    public partial class TEST001 : System.Web.UI.Page
    {
        private List<Book> books = new List<Book>();

        private Dictionary<int, string> dicPublish = new Dictionary<int, string>();

        private int cnt;

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                // 出版社情報定義
                dicPublish.Add(1, "日経BP社");
                dicPublish.Add(2, "技術評論社");
                dicPublish.Add(3, "翔泳社");
                dicPublish.Add(4, "秀和システム");

                Session["GridPublish"] = dicPublish;

                // 書籍情報定義
                books.Add(new Book("978-4-8222-9644-5", "アプリを作ろう! Android入門", 2000, 1, DateTime.ParseExact("2015/08/21", "yyyy/MM/dd", null), false));
                books.Add(new Book("978-4-7741-7568-3", "Angular JSアプリケーションプログラミング", 3700, 2, DateTime.ParseExact("2015/08/19", "yyyy/MM/dd", null), true));
                books.Add(new Book("978-4-7981-4034-6", "10日でおぼえるJSP&サーブレット入門教室", 2800, 3, DateTime.ParseExact("2015/03/16", "yyyy/MM/dd", null), false));
                books.Add(new Book("978-4-7741-7078-7", "サーブレット&JSPポケットリファレンス", 2680, 2, DateTime.ParseExact("2015/01/08", "yyyy/MM/dd", null), false));
                books.Add(new Book("978-4-7980-4179-7", "ASP.NET MVC5 実践プログラミング", 3500, 4, DateTime.ParseExact("2014/09/20", "yyyy/MM/dd", null), true));
                books.Add(new Book("978-4-7981-3546-5", "JavaScript逆引きレシピ", 3000, 3, DateTime.ParseExact("2014/08/28", "yyyy/MM/dd", null), false));
                books.Add(new Book("978-4-7741-6566-0", "PHPライブラリ&サンプル実践活用", 2480, 2, DateTime.ParseExact("2014/06/24", "yyyy/MM/dd", null), false));

                Session["BookInfo"] = books;

                Grid.DataSource = books;
                Grid.DataBind();

            }
            else
            {

            }
        }

        protected void Grid_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            if (e.Row.RowType == DataControlRowType.DataRow)
            {
                cnt++;
                var lblNo = e.Row.FindControl("lblNo") as Label;
                lblNo.Text = cnt.ToString();

                var ddlPublish = e.Row.FindControl("ddlPublish") as DropDownList;
                ddlPublish.DataSource = this.dicPublish;
                ddlPublish.DataTextField = "Value";
                ddlPublish.DataValueField = "Key";
                ddlPublish.DataBind();
            }
        }

        protected void DDLPublish_SelectedIndexChanged(object sender, EventArgs e)
        {
            //senderオブジェクトよりコントロールを取得
            var ddlPublish = (DropDownList)sender;
            var selectedValue = ddlPublish.SelectedValue;

            books = (List<Book>)Session["BookInfo"];
            var BookInfo = books.AsEnumerable().Where(p => p.PublishCd.ToString() == selectedValue).Select(p => new { p.Isbn, p.Title }).ToList();

            //ddlPublishの親コントロールを取得する
            var ddlBook = ddlPublish.Parent.FindControl("ddlBook") as DropDownList;
            ddlBook.DataSource = BookInfo;
            ddlBook.DataTextField = "Title";
            ddlBook.DataValueField = "Isbn";
            ddlBook.DataBind();
        }
    }
}
```

今回は同期ポストバックでの方法でしたが、非同期ポストバックも実装してみたいと思います。