WebSurfer's Home

Filter by APML

GridView に overflow 適用、三点リーダー表示

by WebSurfer 10. November 2015 14:04

GridView の列に長い文字列を入れると、下の画像の「制限しない場合」のように文字列の長さに応じて列の幅が広がっていってしまいます。

それを下の画像の「overflow:hidden で制限」のように、CSS の overflow を使って決まった範囲内に制限する方法について書きます。(テキストが領域をこえた場合に三点リーダー「…」を表示することもできます。詳しくはこの記事の下の方の 2015/11/12 追記を見てください)

GridView に overflow 適用

ASP.NET が GridView を html コードにレンダリングすると table, tr, th, td 要素になります。BoundField を使うと文字列は td 要素の中に直接配置されます。

td 要素はブロックレベル要素ではないのでそれに直接 overflow は適用できません。なので、td 要素の中に div 要素を 配置しそれに overflow 他のスタイルを適用した上で div 要素内に文字列を入れるのがよさそうです。

クライアント側だけで JavaScript を使っても可能ですが、ASP.NET のコードで対応した方が簡単そうです。

具体的には、当該列を TemplateField に変換し、それに div 要素を配置して overflow 他のスタイルを適用、div 要素の中に Literal コントロールを配置してその Text プロパティをデータバインドします。

そのコード例は以下の通りで、これを実行すると上の画像の結果になります。

<%@ Page Language="C#" %>
<%@ Import Namespace="System.Data" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

  protected void Page_Load(object sender, EventArgs e)
  {
    if (!IsPostBack)
    {
      // データソースとして DataTable を作成。
      DataTable dt = new DataTable();
      DataRow dr;

      dt.Columns.Add(new DataColumn("id", typeof(Int32)));
      dt.Columns.Add(
          new DataColumn("description", typeof(string)));

      dr = dt.NewRow();
      dr["id"] = 1;
      dr["description"] = "グリッドビューはデータソースの"+ 
                          "値を表に表示します。";
      dt.Rows.Add(dr);

      dr = dt.NewRow();
      dr["id"] = 2;
      dr["description"] = "The GridView displays the " + 
                      "values of a data source in a table.";
      dt.Rows.Add(dr);

      // 上で作成した DataTable を GridView にバインド。
      GridView1.DataSource = dt;
      GridView1.DataBind();

      GridView2.DataSource = dt;
      GridView2.DataBind();
    }
  }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
  <title>GirdView に overflow 適用</title>
  <style type="text/css">
    div.style1
    {
      width: 150px;
      height: 1.1em;
      overflow: hidden;
    }
  </style>
</head>
<body>
  <form id="form1" runat="server">
  <h2>制限しない場合</h2>
  <asp:GridView ID="GridView1" runat="server">
  </asp:GridView>

  <h2>overflow:hidden で制限</h2>
  <asp:GridView ID="GridView2" 
    runat="server" 
    AutoGenerateColumns="False">
    <Columns>
      <asp:BoundField DataField="id" HeaderText="id" />
      <asp:TemplateField HeaderText="description">
        <ItemTemplate>
          <div class="style1">
            <asp:Literal ID="Literal1" 
              runat="server" 
              Text='<%# Eval("description") %>'>
            </asp:Literal>
          </div>
        </ItemTemplate>
      </asp:TemplateField>
    </Columns>
  </asp:GridView>
  </form>
</body>
</html>

------ 2015/11/12 追記 ------

テキストが領域をこえた場合に三点リーダー「…」を表示する text-overflow:ellipsis はもともと IE の独自拡張だそうですが、最近は他のブラウザでも取り入れられているようです。下の画像は、自分の環境 Vista SP2 32-bit で、Opera 12.17 で試した結果です。

text-overflow:ellipsis 適用

IE9, Chrome 46.0.2490.86 m, Firefox 42.0, Safari 5.1.7 でも同様に text-overflow:ellipsis は有効でした。(古いバージョン、その他のブラウザは未確認です)

上の画像の例ではスタイルを以下のように変更しています。

<style type="text/css">
    div.style1
    {
        width: 150px;
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
    }
</style>

Tags: ,

ASP.NET

DropDownList での NULL の処置

by WebSurfer 23. October 2015 17:19

下の画像のように、GridView などでデータベースの更新操作を行う際 DropDownList を利用してユーザー入力に便宜を図ることがあると思います。その時、NULL を DropDownList でどう対処するかという話を書きます。

GridView 上の DropDownList

ここで紹介する例には Microsoft が提供している Northwind サンプルデータベースの Products テーブルと Categories テーブルを使用しています。

Products テーブルの中の ProductName, CategoryID フィールドを GridView 上で更新する際、CategoryID の列に DropDownList を表示するようにします。

DropDownList には、ユーザーが見ても何だか分からない数字 (CategoryID) を表示するのでははなくて、ユーザーが読んで理解できる名前 (CategoryName) を Categories テーブルから取得して表示します。

Products テーブルの CategoryID には以下のような外部キー制約がかかっていますので、Categories テーブルの CategoryID の値(Northwind サンプルデータベースでは 1 から 8)以外のものは入力できません。

ALTER TABLE [dbo].[Products]  
  ADD CONSTRAINT [FK_Products_Categories] 
  FOREIGN KEY([CategoryID])
  REFERENCES [dbo].[Categories] 
  ([CategoryID])

ただし、NULL は許可されていますので、1 から 8 以外に NULL が入っていることがあります。また、更新の際に NULL を入力したいというケースもあるかもしれません。

先の記事 GridView 上の DropDownList に ToolTip でも同様に DropDownList を使用していますが、そこでは NULL 対応は考えていませんでした。それを以下ように修正して NULL に対応します。

  1. SELECT クエリで INNER JOIN 句に替えて LEFT OUTER JOIN 句を使い CategoryID が NULL のレコードも抽出する。
  2. DropDownList で AppendDataBoundItems="True" とし、以下のような NULL 用の ListItem を追加する。

    <asp:ListItem Value="">NULL</asp:ListItem>

    Value は空白("")にしてください。DropDownList に表示される文字列 NULL は任意のものに変えていいです。データベース上での NULL と ASP.NET コントロール上での空白("")の変換は、ASP.NET の組み込み機能を利用します。その機能についての説明は MSDN ライブラリの記事データ ソース コントロールを使用した、データベースの Null 値の処理を見てください。

具体的なコードは以下の通りです。(分かりやすくするため、先の記事 GridView 上の DropDownList に ToolTip のコードの ToolTip を設定する部分は省いています)

<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
    
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title></title>
</head>
<body>
  <form id="form1" runat="server">
  <div>
    <asp:SqlDataSource ID="SqlDataSource1" 
      runat="server" 
      ConnectionString="<%$ ConnectionStrings:Northwind2 %>" 
      SelectCommand=
        "SELECT TOP 10 
        p.[ProductID], p.[ProductName], 
        p.[CategoryID], c.[CategoryName] 
        FROM [Products] AS p 
        LEFT OUTER JOIN [Categories] AS c 
        ON p.[CategoryID] = c.[CategoryID]
        ORDER BY p.[ProductID]" 
      UpdateCommand=
        "UPDATE [Products] 
        SET [ProductName] = @ProductName, 
        [CategoryID] = @CategoryID 
        WHERE [ProductID] = @ProductID">
      <UpdateParameters>
        <asp:Parameter Name="ProductID" Type="Int32" />
        <asp:Parameter Name="ProductName" Type="String" />
        <asp:Parameter Name="CategoryID" Type="Int32" />
      </UpdateParameters>
    </asp:SqlDataSource>

    <asp:SqlDataSource ID="SqlDataSource2" 
      runat="server" 
      ConnectionString="<%$ ConnectionStrings:Northwind2 %>" 
      SelectCommand=
        "SELECT [CategoryID], [CategoryName], [Description] 
        FROM [Categories]">
    </asp:SqlDataSource>
        
    <asp:GridView ID="GridView1" 
      runat="server" 
      AutoGenerateColumns="False" 
      DataKeyNames="ProductID" 
      DataSourceID="SqlDataSource1">
      <Columns>
        <asp:CommandField ShowEditButton="True" />
        <asp:BoundField DataField="ProductID" 
          HeaderText="ID" 
          InsertVisible="False" 
          ReadOnly="True" 
          SortExpression="ProductID" />
        <asp:BoundField DataField="ProductName" 
          HeaderText="Product Name" 
          SortExpression="ProductName" />
        <asp:TemplateField HeaderText="Category" 
          SortExpression="CategoryName">
          <EditItemTemplate>                        
            <asp:DropDownList ID="DropDownList1" 
              runat="server" 
              DataSourceID="SqlDataSource2" 
              DataTextField="CategoryName" 
              DataValueField="CategoryID" 
              SelectedValue='<%# Bind("CategoryID") %>' 
              AppendDataBoundItems="True">
              <asp:ListItem Value="">NULL</asp:ListItem>
            </asp:DropDownList>
          </EditItemTemplate>
         <ItemTemplate>
            <asp:Label ID="Label1" 
              runat="server" 
              Text='<%# Bind("CategoryName") %>'>
            </asp:Label>
          </ItemTemplate>
        </asp:TemplateField>
      </Columns>
    </asp:GridView>
  </div>
  </form>
</body>
</html>

Tags: , ,

ASP.NET

GridView の最終ページに空行追加

by WebSurfer 7. July 2015 16:14

GridView と SqlDataSource を使用してページングを行う際、最終ページの行数が PageSize より少ない場合、最終データ行の次に即ページャー行が表示されます。(下の画像のように空行は表示されません)

最終ページに空行を挿入

それを、上の画像のように空行を挿入(例えば、PageSize が 10 で、最終ページのデータ行が 7 行の場合、空のデータ行を 3 行追加する)する方法を書きます。

自力でコードを書いて DataTable を作って、それを GridView にデータバインドしているような場合は、DataTable に空行を追加するのが簡単そうですが、GridView と SqlDataSource を組み合わせて使っているような場合はその手が使えません。(ウラワザ的なことをすれば話は別かもしれませんが)

なので、DataTable を細工するのは諦めて、GridView.RowCreated イベントでデータ行の行数を調べ、それが PageSize より少ない場合は空の GridViewRow を追加する方法を取ってみました。

簡単に書くと、(1) ヘッダ行で RowCreated イベントが発生した際にそのセル数を取得。[ヘッダ行のセル数] = [データ行のセル数] というのが前提です、(2) ページャー行で RowCreated イベントが発生した際、[データ行] < [PageSize] であればその差の分空のデータ行を生成し GridView に追加する・・・ということです。

そのコードは以下のようになります。コメントに上記 (1), (2) の詳細を書きましたので見てください。データベースは、Microsoft が提供しているサンプル Northwind の Products テーブルを使っています。

<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

  // データ行のセル数
  int numberOfCells = 0;
    
  protected void GridView1_RowCreated(object sender, 
                                      GridViewRowEventArgs e)
  {
    if (e.Row.RowType == DataControlRowType.Header)
    {
      // ヘッダ行のセル数=データ行のセル数が前提
      numberOfCells = e.Row.Cells.Count;
    }        
    else if (e.Row.RowType == DataControlRowType.DataRow)
    {
      // データ行では何もしない
    }
    else if (e.Row.RowType == DataControlRowType.Footer)
    {
      // フッタ行でも何もしない。ページャー行よりこち
      // らの方のイベント発生が先になるが
    }
    else if (e.Row.RowType == DataControlRowType.Pager)
    {
      // AllowPaging="False" に設定されているとここに
      // 制御は飛んでこない。なので、データ行追加の小
      // 細工はここで行った方がよさそう。
            
      GridView gridView = (GridView)sender;
      int numberOfRows = gridView.Rows.Count;
      int pageSize = gridView.PageSize;

      // データ行 < PageSize の場合、その差の分だけ
      // 空のデータ行とその中身(空セル)を生成
      for (int i = numberOfRows; i < pageSize; i++)
      {
        GridViewRow row = new GridViewRow(
                i,
                -1,
                DataControlRowType.DataRow,
                DataControlRowState.Normal);

        for (int j = 0; j < numberOfCells; j++)
        {
          TableCell cell = new TableCell();
          row.Cells.Add(cell);
        }

        // 空のデータ行を GridView に追加。
        // Collection の中の順番は Footer/Pager 行の
        // 後になるが、HTML にレンダリングされる時は
        // 期待した順序になる。上の GridViewRow のコ
        // ンストラクタで設定した i (RowIndex) と
        // DataControlRowType.DataRow を見ている?
        gridView.Controls[0].Controls.Add(row);
      }           
    }
  }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
  <title></title>
  <style type="text/css">
      table tr
      {
        /* 行(空行を含む)の高さ設定 */
        height: 30px;
      }    
  </style>
</head>
<body>
  <form id="form1" runat="server">
  <div>
    <asp:SqlDataSource ID="SqlDataSource1" 
      runat="server" 
      ConnectionString="<%$ ConnectionStrings:Northwind %>" 
      SelectCommand="SELECT * FROM [Products]">
    </asp:SqlDataSource>

    <asp:GridView ID="GridView1" runat="server" 
      AllowPaging="True" 
      AutoGenerateColumns="False" 
      DataKeyNames="ProductID" 
      DataSourceID="SqlDataSource1" 
      OnRowCreated="GridView1_RowCreated">
      <Columns>
        <asp:BoundField DataField="ProductID" 
          HeaderText="ProductID" InsertVisible="False" 
          ReadOnly="True" SortExpression="ProductID" />
        <asp:BoundField DataField="ProductName" 
          HeaderText="ProductName" 
          SortExpression="ProductName" />
        <asp:BoundField DataField="SupplierID" 
          HeaderText="SupplierID" 
          SortExpression="SupplierID" />
        <asp:BoundField DataField="CategoryID" 
          HeaderText="CategoryID" 
          SortExpression="CategoryID" />
        <asp:BoundField DataField="QuantityPerUnit" 
          HeaderText="QuantityPerUnit" 
          SortExpression="QuantityPerUnit" />
        <asp:BoundField DataField="UnitPrice" 
          HeaderText="UnitPrice" 
          SortExpression="UnitPrice" />
        <asp:BoundField DataField="UnitsInStock" 
          HeaderText="UnitsInStock" 
          SortExpression="UnitsInStock" />
        <asp:BoundField DataField="UnitsOnOrder" 
          HeaderText="UnitsOnOrder" 
          SortExpression="UnitsOnOrder" />
        <asp:BoundField DataField="ReorderLevel" 
          HeaderText="ReorderLevel" 
          SortExpression="ReorderLevel" />
        <asp:CheckBoxField DataField="Discontinued" 
          HeaderText="Discontinued" 
          SortExpression="Discontinued" />
      </Columns>
    </asp:GridView>
  </div>
  </form>
</body>
</html>

Tags:

Paging

About this blog

2010年5月にこのブログを立ち上げました。主に ASP.NET Web アプリ関係の記事です。ブログ2はそれ以外の日々の出来事などのトピックスになっています。

Calendar

<<  April 2026  >>
MoTuWeThFrSaSu
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

View posts in large calendar