WebSurfer's Home

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

TreeView のノードの上下スペーシング

by WebSurfer 2011年10月30日 15:16

TreeView に表示されるノードの上下のスペーシングを調整するにはどうすればいいでしょうか。

TreeView のノード間のスペーシングを調整

子ノードを親ノードに接続する線を表示しない(TreeView.ShowLines プロパティが false)なら NodeStyle-NodeSpacing か NodeStyle-VerticalPadding で設定可能です。

しかし、接続線を表示する場合はそれではうまくいきません。

下の画像は、NodeStyle-VerticalPadding を 10px に設定した TreeView を表示している IE9 とその開発者ツールです(重ねて表示しています)。

NodeStyle-VerticalPadding を 10px に設定

NodeStyle-VerticalPadding を 10px に設定したことにより、td 要素の上下の padding が 10px に設定されてスペーシングは広がったものの、接続線の画像がデフォルトのままなので、線がつながっていません。

線がつながるようにするには、接続線の画像のサイズを大きくする必要があります。(というより、NodeStyle-NodeSpacing や NodeStyle-VerticalPadding は使わないで、画像のサイズだけでスペーシングを調整するようにします。)

接続線の画像は、デフォルトでは TreeView コントロールの埋め込みリソースから 19 x 20 サイズの GIF ファイルがダウンロードされるようになっていますが、以下の手順で変更可能です。

  1. デザイン画面で TreeView の > 印をクリック。
  2. 「TreeView タスク」メニューが表示されるので、[線のイメージのカスタマイズ ...]をクリック。
  3. 「ASP.NET TreeView ラインイメージジェネレーター」ダイアログが表示されるので、Height を指定する(デフォルトは 20)。必要なら、幅も Width の設定で変えられます(デフォルトは 19)。
  4. TreeLineImages フォルダ(存在しなければ自動生成される)の中に、上記 3 で指定したサイズの接続線の GIF イメージファイルが自動的に生成され、配置される(既存の画像ファイルがあれば置き換えられる)。

下の画像は、上記の手順で Height x Width を 40 x 40 に設定して自動生成した接続線の GIF イメージの一部です。

40 x 40 に設定して自動生成した接続線の GIF イメージ

TreeView.LineImagesFolder プロパティに上記 4 の TreeLineImages フォルダを設定し(自動的に設定されます)、上記 3 で画像の幅(Width)を変更していたら TreeView.NodeIndent をそれに合わせて調整します。

でも、これだけではまだ一部で線がつながりません(これはデフォルトの時でも同じです)。下の画像を見てください。

一部で線がつながりません

上の画像が示すように、TreeView.NodeIndent プロパティで設定した幅のインデントを設けるため、td 要素の中に div 要素が配置されています。その場所に接続線がある場合は、その div 要素の中に img 要素を配置して接続線の GIF イメージを表示します。

この例では、NodeIndent="40" としたので div 要素の style 属性で width: 40px; となっています。しかし、height は常に 1px になります。

インデントだけなら height が 1px でも問題ありませんが、接続線を表示する場合は 1px ではダメです。

その問題を解決するには、以下のようなスタイルを定義して、TreeView.CssClass に設定してやります。その結果が一番上の画像です。

<style type="text/css">
    .treeview table td div
    {
        height: 100% !important;
    }    
</style>

Tags: ,

ASP.NET

ページャーの移植

by WebSurfer 2011年10月23日 19:03

BlogEngine.NET バージョン 2.0 に使用されている新しいページャーを、バージョン 1.6.1 のこのブログに移植しました。

新旧ページャーの比較

上の画像では、比較のため、旧ページャー(上の <<前のブログ    次のブログ>> と表示されているもの)と新ページャー(下のページ番号が表示されているもの)を一緒に表示してあります。

具体的な移植方法は以下の通りです。

  • バージョン 2.0 のページャー(カスタムコントロール App_Code/Controls/PostPager.cs)をコピーしてきます。その際、W3C 検証にパスしないAPML フィルターの問題 は処置しておきましょう。また、バージョン 2.0 では名前空間が App_Code.Controls となっているので、バージョン 1.6.1 に合わせて Controls に変更しておきます。
  • User Control/PostList.ascx.cs にバージョン 2.0 のページャーを追加します。さらに、バージョン 1.6.1 のページャーを style="display: none" を追加して消去します。下のサンプルを参考にしてください。
  • User Control/PostList.ascx.cs の Posts プロパティに、ページャーに Post のコレクションへの参照を設定するためのコードを一行追加します。下のサンプルを参考にしてください。
  • 最後に、css を移植します。バージョン 2.0 の Style/Global.css の最後の方にページャー関係のスタイル定義があるので、それをバージョン 1.6.1 の css ファイルにコピーします。バージョン 1.6.1 には Style/Global.css というファイルはないので、自分は、当該テーマの style.css にコピーしました。

User Control/PostList.ascx

<%@ Control Language="C#" 
  AutoEventWireup="true" 
  CodeFile="PostList.ascx.cs" 
  EnableViewState="false" 
  Inherits="User_controls_PostList" %>

<div runat="server" id="posts" class="posts" />

<div id="postPaging" style="display: none">
  <a runat="server" 
    ID="hlPrev" 
    style="float:left">
    << <%=Resources.labels.previousPosts %>
  </a>
  <a runat="server" 
    ID="hlNext" 
    style="float:right">
    <%=Resources.labels.nextPosts %> >>
  </a>
</div>

<%--2011/10/23 BlogEngine.NET 2.0 のページャー 
  (App_Code/Controls/PostPager.cs) を移植。
  旧ページャーは div id="postPaging" に 
  style="display: none" として消去。--%>
<div style="clear:both; display:block">
  <blog:PostPager ID="pager1" 
    runat="server">
  </blog:PostPager>
</div>

User Control/PostList.ascx.cs

// ・・・前略・・・

public partial class User_controls_PostList : UserControl
{

  // ・・・中略・・・

  private List<IPublishable> _Posts;
  /// <summary>
  /// The list of posts to display.
  /// </summary>
  public List<IPublishable> Posts
  {
    get 
    { 
      return _Posts; 
    }
    set 
    { 
      _Posts = value;

      // 2011/10/23 BlogEngine.NET 2.0 のページャー
      // (App_Code/Controls/PostPager.cs) を移植した
      // ので以下のコードを追加。
      this.pager1.Posts = value;
    }

  // ・・・中略・・・

}

Tags:

BlogEngine.NET

パスワードに有効期限を設定

by WebSurfer 2011年10月22日 16:31

Forms 認証でパスワードに有効期限を設定するにはどうしたらよいでしょうか?

有効期限切れパスワードの変更

有効期限を知るためのデータ(例えば、最初にアカウントを作成した日時またはパスワードを変更した日時)をデータベースに記録し、ユーザーがログインした際にそのデータを取得して期限が過ぎているか否かの判断をするという操作が必要です。

組み込みの機能にそのようなものはないと思っていましたが、よく調べてみたら、標準の Forms 認証用 SQL Server データベースの aspnet_Membership テーブルに LastPasswordChangedDate というフィールドがあり、それを取得するために MembershipUser.LastPasswordChangedDate プロパティ が用意されていました。

これを利用すれば、パスワードに有効期限を設け、ユーザーがログインする際に有効期限が過ぎていたら ChangePassword コントロール を表示して、ユーザーにパスワード変更を促すというような操作が簡単に可能になります。

以下のコードは、パスワードの有効期限を 90 日とし、ユーザーがログインする際に 90 日を過ぎていたら Login コンロトールを非表示にするとともに ChangePassword コントロールを表示し(上の画像がそれです)、パスワードを変更したら Login コンロトールを再度表示して新しいパスワードでログインするというシナリオになっています。

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

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

<script runat="server">

  double expireDays = 90;

  protected void Login1_LoggingIn(object sender, 
    LoginCancelEventArgs e)
  {
    MembershipUser user = 
      Membership.GetUser(Login1.UserName);

    if (user == null)
    {
      // MembershipUser が取得できなければその後の
      // 処置は Login コントロールに任せる。
      return;
    }

    if (user.LastPasswordChangedDate.AddDays(expireDays) <
      DateTime.Now)
    {
      Msg.Visible = true;
      Msg.Text = "パスワードが有効期限を過ぎています。";
      ChangePassword1.UserName = Login1.UserName;
      ChangePasswordPanel.Visible = true;
      LoginPanel.Visible = false;
      e.Cancel = true;
    }
    else
    {
      Msg.Visible = false;
    }
  }

  protected void _ChangingPassword(object sender, 
    LoginCancelEventArgs e)
  {
    if (ChangePassword1.CurrentPassword == 
      ChangePassword1.NewPassword)
    {
      Msg.Visible = true;
      Msg.Text = "新旧パスワードが同じです。";
      e.Cancel = true;
    }
    else
    {
      Msg.Visible = false;
    }        
  }

  protected void _ChangedPassword(object sender, EventArgs e)
  {
    ChangePasswordPanel.Visible = false;
    LoginPanel.Visible = true;
    Msg.Visible = true;
    Msg.Text = "新しいパスワードでログインしてください。";
  }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
  <title>Login</title>
</head>
<body>
  <form id="form1" runat="server">
    <h3>有効期限つきパスワードでのログイン操作</h3>

    <asp:Label id="Msg" 
      runat="server" 
      ForeColor="maroon"  
      Visible="False" />
    <br />

    <asp:Panel ID="LoginPanel" 
      runat="server">
      <asp:Login ID="Login1" 
        runat="server" 
        DisplayRememberMe="False" 
        OnLoggingIn="Login1_LoggingIn">
      </asp:Login>
    </asp:Panel>

    <asp:Panel ID="ChangePasswordPanel" 
      runat="server" 
      Visible="False">
      <asp:ChangePassword ID="ChangePassword1" 
        runat="server" 
        DisplayUserName="True" 
        OnChangingPassword="_ChangingPassword" 
        OnChangedPassword="_ChangedPassword" 
        CancelDestinationPageUrl="~/Default.aspx">
      </asp:ChangePassword>
    </asp:Panel>
  </form>
</body>
</html>

参考にしたのは MembershipUser.LastPasswordChangedDate プロパティChangePassword.CurrentPassword プロパティ のサンプルコードです。

Tags: ,

Authentication

About this blog

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

Calendar

<<  2024年4月  >>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

View posts in large calendar