WebSurfer's Home

トップ > Blog 1   |   ログイン
APMLフィルター

DataGridView に ID と名前を併記

by WebSurfer 2014年2月1日 15:48

先の記事 DataGridView に ComboBox を表示 では CategoryID, SupplierID(数字)に代えて、名前を Categories, Suppliers テーブルから取得して ComboBox に表示する方法を書きました。

ComboBox など使わないで、ID と名前の両方を並べて表示すればよいというケースもあると思います。ここでは、Northwind サンプルデータベースの Products テーブルと Categories テーブルを例に使い、下の画像のように CategoryID と CategoryName を並べて表示する方法を書きます。なお、Visual Studio の TableAdpter 構成ウィザードを利用してアプリを作るのが前提です。

DataGridView に ID と名前を表示

たぶん最初に考え付くのは、TableAdpter 構成ウィザードで、以下のように INNER JOIN した SELECT クエリをベースに型付 DataSet + TableAdapter を作ることではないでしょうか?

SELECT Products.ProductID, Products.ProductName, 
       Products.CategoryID, Categories.CategoryName,
       Products.UnitPrice, Products.Discontinued
FROM   Products INNER JOIN Categories 
ON     Products.CategoryID = Categories.CategoryID

しかしながら、テーブルを JOIN した SELECT クエリをベースに TableAdapter を自動生成させると UPDATE, DELETE, INSERT に必要なコードは一切自動生成されません。

表示するだけではなく、Products テーブルは更新する必要があるという場合、以下のように TableAdpter 構成ウィザードのクエリビルダで、単一の Products テーブルを対象とする SELECT クエリをベースに TableAdapter を生成すれば、Products テーブルを更新するのに必要なメソッドを自動生成してくれます。

クエリビルダ

上の画像の SELECT クエリは以下の通りです。CategoryName を抽出する部分はクエリビルダは自動的には作ってくれませんので、自力で書く必要があります。

SELECT ProductID, ProductName, CategoryID,
       (SELECT CategoryName FROM Categories
        WHERE (Products.CategoryID = CategoryID))
       AS CategoryName,
       UnitPrice, Discontinued
FROM   Products

型付 DataSet + TableAdapter が完成したら、データソースウィンドウを開くとその中に Products という項目があるはずなので、それを Form にドラッグ&ドロップするだけで、DataGridView 上で Products テーブルの表示、編集、更新ができるアプリが完成するはずです。

DataDridView の CategoryName 列の dataGridViewTextBoxColumn は Visual Studio が自動的に ReadOnly = true に設定して生成してくれます(ユーザー入力はできないようになります)。

なお、上記は Products テーブルのみ更新をできればよいというケースですので注意してください。Products テーブルと Categories テーブルの両方を同時に更新したい場合は TableAdapterManager で紹介したように階層更新が可能な形にする必要があります。

Tags: ,

.NET Framework

DataGridView に ComboBox を表示

by WebSurfer 2014年1月23日 15:26

DataGridView の特定の列を ComboBox を使って表示する方法を備忘録として書いておきます。

DataGridView に ComboBox を表示

Northwind サンプルデータベースの Products テーブルを例に使い、上の画像のように Category 列と Supplier 列を ComboBox を使って表示します。

Products テーブルを DataGridView に表示して更新操作ができるようにするだけなら、自分でコードは一行も書かなくても、Visual Studio のウィザードを使ってドラッグ&ドロップ操作だけで Windows Form アプリを作成できます。

ただし、Products テーブルの中の CategoryID, SupplierID は ID(数字)で表示されるので、そのままではユーザーにとっては分かりにくいです。

ID に代えて、名前を Categories, Suppliers テーブルから取得して表示した方がユーザーにとっては分かりやすいはずです。

さらにユーザーがデーターベースを編集・更新する場合は、ComboBox を使用してドロップダウン形式で一覧を表示し、その中からユーザーが選択できるようにするとさらにユーザーフレンドリーになると思います。

今回の例では、CategoryID, SupplierID 列に ComboBox を使い、各行の CategoryID, SupplierID に該当する名前(CategoryName, CompanyName)を Categories, Suppliers テーブルから取得して ComboBox に表示するようにします。

Category 列の方は Visual Studio のウィザードを利用して、自力では一行もコードを書かずに ComboBox を実装してみます。

Supplier 列の方は自力でコードを書いて DataTable を作成し、それを ComboBox の DataSource に設定することにします。

以下にその手順を書きます。

  1. Visual Studio の[ファイル(F)]⇒[新しいプロジェクト(P)...]メニューから[Windows フォームアプリケーション]テンプレートを使って空のプロジェクトを作成する。
  2. ソリューションエクスプローラーでプロジェクトのルートを右クリック。[追加(D)]⇒[新しい項目(W)...]⇒[データセット]で適当な名前(例えば NorthwindDataSet.xsd)をつけて空の xsd ファイルを作成。(注:下の画像はステップ 12 まで進んだ時の完成済みのデータセットで、このステップの時点では何も表示されていません)

NorthwindDataSet.xsd ファイル

  1. ツールボックスから TableAdapter をドラッグ&ドロップすると TableAdapter 構成ウィザードが立ち上がる。
  2. クエリビルダで以下の SELECT クエリを作り、これをベースに DataTable + TableAdapter を作る。

    SELECT ProductID, ProductName, CategoryID, SupplierID,
    UnitPrice, Discontinued FROM Products

    DataGridView に表示するとともに編集・更新操作を行うのはこれなので、TableAdapter 内に作成する更新系のメソッド等の生成オプションはフルにチェックを入れておく。
  3. TableAdapter 構成ウィザードでの操作が完了すると、ProductsDataTable と ProductsTableAdapter が自動生成されているはず。(上の NorthwindDataSet.xsd ファイルの画像で、左側の箱)
  4. Form1.cs を開きそのデザイン画面を表示する。データソースウィンドウを開くとその中に Products という項目があるはずなので、それを Form にドラッグ&ドロップする。
  5. 上のステップまでで、Products テーブルの表示、編集、更新ができるアプリが完成するはず。とりあえずこの段階で DataGridView への表示、レコードの INSERT, DELETE, UPDATE が問題なくできることを確認しておく。
  6. 上記が確認できたら、最初に Category の方を ComboBox で表示するための設定を行う。
  7. 自力でコードを書くのは必要最小限にするため、TableAdapter 構成ウィザードを利用して DataTable + TableAdapter を作り、これを利用する。
  8. NorthwindDataSet.xsd ファイルを開き、ツールボックスからもう一つ TableAdapter をドラッグ&ドロップする。
  9. TableAdapter 構成ウィザードが立ち上がるので、クエリビルダで以下の SELECT クエリを作り、これをベースに DataTable + TableAdapter を作成する。

    SELECT CategoryID, CategoryName FROM Categories

    こちらは、CategoryID に該当する CategoryName を ComboBox を使って表示するためのデーターソースとして利用するだけなので、TableAdapter に更新系のメソッドは不要。
  10. TableAdapter 構成ウィザードでの操作が完了すると、CategoriesDataTable と CategoriesTableAdapter が自動生成されているはず。(上の NorthwindDataSet.xsd ファイルの画像で、右側の箱)
  11. DataGridView の列の編集画面で、CatrgoryID 列の ColumnType を DataGridViewComboBoxColumn に変更する。

列の編集画面その1

  1. 上の画面で、DataSource を[他のデータソース]⇒[プロジェクトデータソース]⇒[NorthwindDataSet]⇒[Catrgories]に設定すると、自動的に categoriesBindingSource が生成され、DataSource に設定される。
  2. 次に、DisplayMember を CategoryName に、ValueMember を CategoryID に設定する。

列の編集画面その2

  1. ここまでの操作で、Category の方は ComboBox で表示され、編集する際は ComboBox をドロップダウンしてその中から選択して更新をかけることが可能になるはず。
  2. 次に、Supplier の方を ComboBox に表示するための設定を行う。こちらは TableAdapter 構成ウィザードを使用しないで、自力でコードを書いて DataTable を作り、それをデーターソースに利用してみる。
  3. Category の場合と同様に、DataGridView の列の編集画面で、SupplierID 列の ColumnType を DataGridViewComboBoxColumn に変更する。
  4. その先は自力でコードを書いて DataTable を作成し、それを DataGridViewComboBoxColumn の DataSource に設定する。
  5. Form1.cs のコード画面を開く。
  6. ADO.NET のライブラリを使い、Suppliers テーブルから SupplierID, CompanyName を取得し DataTable を作成するコードを追加する。具体例は以下のサンプルコードの CreateSuppliersTable を参照。
  7. Form1_Load メソッド(自動生成されているはず)の中に、上記 18 の手順で作成した DataGridViewComboBoxColumn の DataSource プロパティを CreateSuppliersTable メソッドが返す DataTable に、DisplayMember プロパティを "CompanyName" に、ValueMember プロパティを "SupplierID" に設定する。具体例は以下のサンプルコードを参照。
  8. 以上の操作で、一番上の画像のアプリが完成するはずです。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;  // 要追加

namespace DataGridViewComboBox
{
  public partial class Form1 : Form
  {
    public Form1()
    {
      InitializeComponent();
    }

    private void productsBindingNavigatorSaveItem_Click(
        object sender, EventArgs e)
    {
      this.Validate();
      this.productsBindingSource.EndEdit();
      this.tableAdapterManager.UpdateAll(
          this.northwindDataSet);
    }

    private void Form1_Load(object sender, EventArgs e)
    {
      this.categoriesTableAdapter.Fill(
          this.northwindDataSet1.Categories);
      this.productsTableAdapter.Fill(
          this.northwindDataSet.Products);
      // ここまでのコードは Visual Studio のウィザードで
      // 自動生成される。


      // ここから下のコードを自力で書いて追加する。

      // DataSource に設定するのは Supplier の ComboBox に
      // 表示するデータを含む DataTable。下のヘルパーメソッ
      // ド CreateSuppliersTable で作成。
      this.dataGridViewTextBoxColumn4.DataSource = 
          CreateSuppliersTable();
      this.dataGridViewTextBoxColumn4.DisplayMember = 
          "CompanyName";
      this.dataGridViewTextBoxColumn4.ValueMember = 
          "SupplierID";
    }

    // Suppliers テーブルから SupplierID, CompanyName を抽出
    // して DataTable を作るためのヘルパーメソッド。
    private DataTable CreateSuppliersTable()
    {
      DataTable table = new DataTable("Suppliers");
      table.Columns.Add(
            new DataColumn("SupplierID", typeof(int)));
      table.Columns.Add(
            new DataColumn("CompanyName", typeof(string)));

      string connString = DataGridViewComboBox.Properties.
          Settings.Default.NORTHWNDConnectionString;
      string query = 
          "SELECT SupplierID, CompanyName FROM Suppliers " + 
          "ORDER BY SupplierID";

      using (SqlConnection conn = new SqlConnection(connString))
      {
        conn.Open();
        using (SqlCommand cmd = new SqlCommand(query, conn))
        {
          using (SqlDataReader reader = cmd.ExecuteReader())
          {
            if (reader != null)
            {
              while (reader.Read())
              {
                DataRow row = table.NewRow();
                row["SupplierID"] = reader.GetInt32(0);
                row["CompanyName"] = reader.GetString(1);
                table.Rows.Add(row);
              }
            }
          }
        }
      }
      return table;
    }

  }
}

Tags: , ,

.NET Framework

ASP.NET の ID オブジェクト

by WebSurfer 2014年1月20日 16:36

ASP.NET Web Forms アプリケーションの Page 内では、以下の 3 つのプロパティ/メソッドで ID オブジェクト(WindowsIdentity または GenericIdentity)を取得できます。

それぞれどのように違うかを調べましたので、備忘録として書いておきます。


HttpRequest.LogonUserIdentity

現在 IIS が HTTP 要求を受けているユーザーの WindowsIdentity(Windows ユーザーを表す)オブジェクトを取得します。

匿名アクセス(Page.User.Identity.IsAuthenticated が false)の場合は常に IUSR となります。IUSR とは、匿名認証が有効化されている場合は常に IIS によって使用される既定の ID です。

ログイン済みユーザー(Page.User.Identity.IsAuthenticated が true)の場合は認証方式によって異なり、以下の通りとなります。

  • フォーム認証:ワーカープロセス(例:IIS7 では NETWORK SERVICE)
  • Windows 認証:ログインユーザーの Windows アカウント

ASP.NET 偽装の有効・無効には影響を受けず、常に上記の通りとなります。


WindowsIdentity.GetCurrent

ASP.NET 偽装が無効になっている場合は、ワーカープロセスを実行しているアカウント(IIS7 では NETWORK SERVICE)の WindowsIdentity オブジェクトを取得します。

ASP.NET 偽装が有効になっている場合は、偽装の設定方法、認証方式、匿名アクセスかログイン済みかによって、取得される WindowsIdentity オブジェクトは異なります(「偽装」しているだけで、実際にワーカープロセスを実行しているアカウントは変わらないのかもしれません・・・未確認です)。

web.config での偽装の設定を、単純に <identity impersonate="true" /> とした場合には以下のようになります。

フォーム認証

  • 匿名アクセス:IUSR
  • ログイン済み:ワーカープロセス(例:IIS7 では NETWORK SERVICE)

Windows 認証

  • 匿名アクセス:IUSR
  • ログイン済み:ログインユーザーの Windows アカウント

上記の偽装の設定に userName 属性、password 属性の設定を追加し、特定の Windows ユーザーアカウントを偽装した場合は、認証方式や認証済みか否かに関わらず、常に userName 属性に設定したユーザーアカウントになります。


Page.User.Identity

現在ページ要求を行っているユーザーを表す ID オブジェクトを取得します。

Page.User プロパティは、Windows 認証が有効になっている場合は WindowsPrincipal を、Windows 認証が無効の場合は RolePrincipal(ロール メンバシップを含む現在の HTTP 要求のセキュリティ情報)を取得します。

そして、WindowsPrincipal.Identity からは WindowsIdentity オブジェクトが、RolePrincipal.Identity からは GenericIdentity(標準ユーザーを表す)が取得されます。

ただし、それらの中身は ASP.NET が書き換えており、特に Name は、匿名アクセスの場合は IUSR ではなく空文字になること、フォーム認証のログイン済みユーザーの場合は Windows アカウント名ではなくフォーム認証のユーザー ID となる点に注意してください。

具体的には、IsAuthenticated, AuthenticationType, Name プロパティは以下の通りとなります。

フォーム認証、匿名アクセス

  • IsAuthenticated: false
  • AuthenticationType:(空文字)
  • Name:(空文字)

フォーム認証、ログイン済み

  • IsAuthenticated: true
  • AuthenticationType: Forms
  • Name: フォーム認証のユーザー ID

Windows 認証、匿名アクセス

  • IsAuthenticated: false
  • AuthenticationType:(空文字)
  • Name:(空文字)

Windows 認証、ログイン済み

  • IsAuthenticated: true
  • AuthenticationType: Negotiate
  • Name: ログインユーザーの Windows アカウント

Tags:

ASP.NET

About this blog

2010年5月にこのブログを立ち上げました。主に ASP.NET Web アプリ関係の記事です。

Calendar

<<  2024年3月  >>
252627282912
3456789
10111213141516
17181920212223
24252627282930
31123456

View posts in large calendar