WebSurfer's Home

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

ブラウザ画面でセンタリング

by WebSurfer 2018年11月1日 12:10

CSS のみを使ってブラウザ画面上でコンテンツを上下左右センタリングする方法を、あまり需要はないとは思いますが、せっかく考えたので備忘録として書いておきます。

センタリング表示

上の画像は、width / height を 500px / 300px に設定した div 要素を、CSS の position プロパティを使って、ブラウザ画面の中央に来るようにしたものです。ブラウザの画面のサイズを変えても自動的に中央に来るようになっています。

CSS の設定は下にアップしたコードにありますので見てください。position を absolute とし、top / left を 50%(即ち画面の中央)に指定、margin に div 要素のサイズの半分をマイナス値で設定することにより div 要素が画面の中央に来るようにオフセットしています。

position プロパティの詳しい説明&デモは MDN web docs の記事「position」にありますので見てください。要点を抜粋すると以下の通りです。

An absolutely positioned element is an element whose computed position value is absolute or fixed. The top, right, bottom, and left properties specify offsets from the edges of the element's containing block. If the element has margins, they are added to the offset.

上の画像を表示したコードを以下にアップしておきます。ASP.NET Web Forms アプリの .aspx ページを使っていますが、ASP.NET は今回の記事には直接の関係はありません。(.html ページを使うとブラウザのキャッシュをいちいち消さなければならないのが面倒なので .aspx ページを使いました)

<%@ Page Language="C#" AutoEventWireup="true" 
    CodeFile="0049-Centering.aspx.cs" 
    Inherits="_0049_Centering" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Centering</title>
    <style type="text/css">
        body {
            background-color: #555;
        }

        .content {
            background-color: white;
            width:500px;
            height:300px;
            position:absolute;
            top:50%;
            left:50%;
            margin-left:-250px;
            margin-top:-150px;
            overflow:scroll;
        }
    </style>
</head>
<body>
  <form id="form1" runat="server">
    <div class="content">
      <h1>
        This page is horizontally / vertically centered on 
        screen that is wider than 500 / 300 pixels.
      </h1>
      <h2>
        Resize the browser window to see the effect.
      </h2>
      <p>
        An absolutely positioned element is an element 
        whose computed position value is absolute or fixed. 
        The top, right, bottom, and left properties specify 
        offsets from the edges of the element's containing 
        block. (The containing block is the ancestor 
        relative to which the element is positioned.) 
        If the element has margins, they are added to the 
        offset.
      </p>
    </div>
  </form>
</body>
</html>

Tags:

ASP.NET

SqlDataSource を使わず GridView をソート

by WebSurfer 2018年10月22日 13:15

SqlDataSource などのデータソースコントロールを使わないで GridView の各列にソート機能を実装するにはどうすればいいかということを書きます。

GridView の Sorting

元は MSDN Forum のスレッド「SqlDataSourceを使わずに、GridViewの並べ替えができますでしょうか?」の話です。

MSDN ライブラリ GridView Class の「データへのバインド」のセクションに書いてありますが、GridView はデータソースコントロール(SqlDataSource, ObjectDataSource など)と連携して並べ替え、更新、削除、およびページング機能を提供しています。

逆に言えば、データソースコントロールを使わないと、ソート、更新、削除、およびページング機能が必要な場合、全て自力でコードを書いて実装することになります。

以下に、例としてソート機能を自力で GridView に実装する方法を書きます。

ソートを行うために GridView と SqlDataSource の中でどのような操作が行われているかは不明ですが、おそらく、取得したデータから DataView を作って、その Sort プロパティ に SortExpression を設定し、ソートした結果を GirdView に表示していると思われます。

そのあたりの処理を自力でコードを書いて実装してみます。

昇順に並べ替えるだけなら、GridView.Sorting イベントのハンドラで、DataView の Sort プロパティを引数の GridViewSortEventArgs オブジェクトから取得できる SortExpression に設定するだけで可能です。

SqlDataSource + GridView を使った場合、同じ LinkButton のクリックを繰り返すと ASC / DESC が切り替わりますが、そこまで同じにしようとするとちょっと面倒です。

SqlDataSource + GridView でそれをどのように実現しているか分かりませんが、GridView の属性に CurrentSortField, CurrentSortDir というのを追加し、それに前回クリックされた LinkButton の SortExpression およびその時 ASC or DESC どちらだったかの情報を保持することを考えてみました。

そのソースコードを以下にアップしておきます。このコードの実行結果が上の画像の GridView です。ヘッダの Name を 2 回クリックして降順に並べ替えています。

.aspx.cs ファイル

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

public partial class _0055_GridViewSorting : System.Web.UI.Page
{
    // データソース用の DataView を作成
    protected DataView CreateDataSource()
    {
        DataTable dt = new DataTable();
        DataRow dr;

        dt.Columns.Add(new DataColumn("ID", typeof(Int32)));
        dt.Columns.Add(new DataColumn("Name", typeof(string)));
        dt.Columns.Add(new DataColumn("Type", typeof(string)));
        dt.Columns.Add(new DataColumn("Price", typeof(Int32)));
        dt.Columns.Add(new DataColumn("Qty", typeof(Int32)));
        dt.Columns.Add(new DataColumn("Amount", typeof(Int32)));
        dt.Columns.Add(new DataColumn("CatID", typeof(Int32)));
        dt.Columns.Add(new DataColumn("Note", typeof(string)));
        dt.Columns.Add(new DataColumn("Disc", typeof(bool)));
        dt.Columns.Add(new DataColumn("Date", typeof(DateTime)));

        for (int i = 0; i < 15; i++)
        {
            dr = dt.NewRow();
            dr["ID"] = i;
            dr["Name"] = "Product Name_" + i.ToString();
            dr["Type"] = "Product Type " + (100 - i).ToString();
            dr["Price"] = 123000 * (i + 1);
            dr["Qty"] = (i + 1) * 20;
            dr["Amount"] = 123000 * (i + 1) * (i + 1);
            dr["CatID"] = 100 - i;
            dr["Note"] = "Note_" + i.ToString();
            dr["Disc"] = (i % 2 == 0) ? true : false;
            dr["Date"] = DateTime.Now.AddDays(i);
            dt.Rows.Add(dr);
        }
        return new DataView(dt);
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            GridView1.DataSource = CreateDataSource();
            GridView1.DataBind();
        }
    }

    protected void GridView1_Sorting(object sender, 
                                      GridViewSortEventArgs e)
    {
        GridView gv = (GridView)sender;
        DataView view = CreateDataSource();
        string exp = e.SortExpression;

        // 同じ LinkButton をクリックした場合 ASC / DESC を切り
        // 替えるための処理。
        // GridView の属性に CurrentSortField, CurrentSortDir 
        // を追加し、それに前回クリックされた LinkButton の 
        // SortExpression およびその時 ASC or DESC どちらだった
        // かの情報を保持。
        if (gv.Attributes["CurrentSortField"] != null &&
            gv.Attributes["CurrentSortDir"] != null)
        {
            if (exp == gv.Attributes["CurrentSortField"])
            {
                if (gv.Attributes["CurrentSortDir"] == "ASC")
                {
                    exp = exp + " DESC";
                    gv.Attributes["CurrentSortDir"] = "DESC";
                }
                else
                {
                    exp = exp + " ASC";
                    gv.Attributes["CurrentSortDir"] = "ASC";
                }
            }
            else
            {
                gv.Attributes["CurrentSortField"] = exp;
                exp = exp + " ASC";
                gv.Attributes["CurrentSortDir"] = "ASC";
            }
        }

        view.Sort = exp;
        gv.DataSource = view;
        gv.DataBind();
    }
}

.aspx ファイル

<%@ Page Language="C#" AutoEventWireup="true" 
    CodeFile="0055-GridViewSorting.aspx.cs" 
    Inherits="_0055_GridViewSorting" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:GridView ID="GridView1" runat="server" 
            AllowSorting="True"
            CurrentSortField=""
            CurrentSortDir=""
            onsorting="GridView1_Sorting">
        </asp:GridView>
    </form>
</body>
</html>

上のコードを見ると、自力で一行もコードを書く必要のない SqlDataSource を使う方が正解と思えます。何らかの理由で SqlDataSource を使えない場合でも、上に紹介した MSDN Forum の記事に書いてあるように ObjectDataSource を使うという手段もあります。

Tags: ,

ASP.NET

「常にコピーする」の意味

by WebSurfer 2018年9月29日 13:32

下の画像の「常にコピーする」の「常に」の意味が、Visual Studio 2010 と Visual Studio 2015(以下、VS2010、VS2015 と書きます)では違っているという話を書きます。

出力ディレクトリにコピー

どう違うかと言うと、VS2010 ではソースコードを変更してリビルドしてから実行した場合にコピーされますが、VS2015 ではソースコードは一切変更しなくても実行するたびコピーされます。SQL Server Express のユーザーインスタンスだけでなく LocalDB の場合も同じです。

それを知らないと上記の機能を利用したアプリの開発の際、期待した結果にならなくて焦るかもしれません。何を隠そう自分がそうだったのですが。(笑) どういうことだったかと言うと以下の通りです。

開発中のアプリで DB に INSERT, DELETE, UPDATE 等の操作をしてから一旦アプリを閉じた後、DB に反映された結果を見るために、再度アプリを実行して DB の内容を表示するということがあると思います。

そういう場合、VS2010 では編集結果が表示されますが、VS2015 では編集前の元のファイルがコピーされてそれを見ることになるので、アプリが期待通り動いてないと勘違いして焦るということです。(笑)

話としては以上なのですが、それだけではブログの記事としては書き足りない気がしましたので、少し追加情報を書いておきます。

普通に SQL Server に接続してアプリを開発しようとすると、SQL Server の既定のインスタンス(または、名前付きインスタンス)に接続することになります。

既定のインスタンス(または、名前付きインスタンス)を使えるようにするには SQL Server 側の設定がいろいろ面倒ですし、そこがクリアできても Visual Studio の Express 版からでは接続できないという問題もありました。

なので、SQL Server の Express 版のユーザーインスタンスや LocalDB を使って、アプリを起動する都度 .mdf ファイルをアタッチして接続するというファイルベースの開発を行う機能が提供されています。

その際「出力ディレクトリにコピー」の設定で、出力ディレクトリに .mdf ファイルをコピーを作成してそれをアタッチする設定にすることができます。

出力ディレクトリとは Windows Forms アプリの場合は .exe ファイルが出力されるフォルダ、ASP.NET Web アプリの場合は App_Data フォルダになります。接続文字列では |DataDirectory| と指定されます。

その「出力ディレクトリにコピー」のデフォルトが「常にコピーする」になります。

「常にコピーする」の他に「コピーしない」「新しい場合はコピーする」というオプションがあります。詳しくは、@IT の記事「Visual Studio 2005でデータベースの更新が反映されない場合には?」を見てください。

VS2005 は上の記事によると「再度アプリケーションをデバッグ実行すると、そのDBファイルは上書きされてしまう」とのことです。VS2008、VS2013、VS2017 等ではどうなるか不明です。

Tags: ,

DevelopmentTools

About this blog

2010年5月にこのブログを立ち上げました。その後 ブログ2 を追加し、ここは ASP.NET 関係のトピックス、ブログ2はそれ以外のトピックスに分けました。

Calendar

<<  2018年11月  >>
28293031123
45678910
11121314151617
18192021222324
2526272829301
2345678

View posts in large calendar