2019/04/22(月)WebFormでDOMを扱う

ページ内にGridViewが複数あり、一番上のGridViewに表示されたセルのテキストをクリックすると、2番目、3番目のGridView内の同じテキストをハイライトしたい(テキストコピーしてCTRL+Fでページ内検索していたがコピーペーストが面倒)という非常にレアなシチュエーション。
WebFormでjQueryや他のライブラリ使うよりは直接DOMの配列ぐるぐる回した方が楽そう。
<script type="text/javascript">
    function highlightKeyword(keyword) {
        var tbls = document.getElementsByTagName("table");
        // 一番上のテーブルを除く全てのテーブルの全ての行の全てのセル内を置換
        for (var i = 1; i < tbls.length; i++) {
            for (var j = 1; j < tbls[i].rows.length; j++) {
                for (var k = 0; k < tbls[i].rows[j].cells.length; k++) {
                    var str = tbls[i].rows[j].cells[k].innerHTML;
                    // 既にタグが付いてるかも知れないので削除してから追加
                    tbls[i].rows[j].cells[k].innerHTML = str.replace('<span style="background: yellow;">', '').replace('</span>', '').replace(keyword, '<span style="background: yellow;">' + keyword + '</span>');
                }
            }
        }
    }
</script>

2019/04/14(日)ASP.NET WebFormのMenuコントロール その3

WebFormのテストプロジェクトに過去に試したものも統合しておこうとMenuコントロールを追加したら、Bootstrapのバージョン上げた(4.3.1)ためにデザインが崩れてまたやり直し…。

ここまでは順調
menucontrol.png


幅を寄せるをなぜかトグルボタンの位置がずれる
menucontrol2.png


メニューを開くと正常な位置に
menucontrol3.png


なんとなくあと一息、と言う感じだったのでメニューコントロール使わない正常パターンと使った時のずれるパターンでソースを見比べながら頑張りましたが違いが見つけ出せず。

menuコントロールの一番外側がdivになっていたので、CssClassプロパティにcollapse navbar-collapseをセットしていたのですがそれをやめ、divタグで囲んだらちゃんと表示されるようになりまた。
<nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
    <a class="navbar-brand" runat="server" href="~/">テスト用</a>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbar" aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbar">
        <asp:Menu ID="mainmenu" DataSourceID="SiteMapDataSource1"
            runat="server" 
            Orientation="Horizontal" 
            StaticDisplayLevels="2"
            StaticEnableDefaultPopOutImage="False"
            MaximumDynamicDisplayLevels="10" 
            EnableViewState="false"
            StaticMenuStyle-CssClass="navbar-nav mr-auto" 
            StaticSelectedStyle-CssClass="active"
            DynamicMenuStyle-CssClass="dropdown-menu" 
            IncludeStyleBlock="false" 
            SkipLinkText=""
            RenderingMode="List"
            StaticMenuItemStyle-CssClass="nav-link"
            DynamicMenuItemStyle-CssClass="dropdown-item">
        </asp:Menu>
    </div>
</nav>

2017/07/22(土)ASP.NET WebFormのMenuコントロール その2

PC専用(タブレット含む?)ということであれば、Menuコントロールのプロパティだけで何とかなりそうです。
こちらからそのまま貰ってきて、エラーの出るOnMenuItemClick="Menu1_MenuItemClick"を削除、DataSourceIDにサイトマップのIDを設定。
MaximumDynamicDisplayLevels="10"とあるので、頑張ってデータ作ってみました。
bootstrap風Menuコントロール

bootstrapのドロップダウンは1層だけですが、WebFormのMenuコントロール用cssとの合わせ技でしょうか、8層くらいまでなら表示できそうです。右端に到達したら折り返してきてくれるかなと試しましたが、表示が切れました。

WebFormは社内用のアプリで多く使っていて今まではPCかつIE専用で押し通すことも可能でしたが、最近はスマホからVPN経由で使いたい、と言うような要望も出てきています。
スマホのことを考えると干渉するかもしれないcssの合わせ技は、不具合の出る端末見つかった時には手に負えないかも。

スマホ用のサイズでデザインが崩れないようにするには、jQueryでMenuコントロールのcssを取り除け、という情報が多いようです。一番詳しいのはこちら。個人的にjQueryでcssやstyleいじるくらいならC#でSiteMapデータをグリグリしたい派なので、実際には試していません。

2017/07/20(木)ASP.NET WebFormのMenuコントロールに苦戦中

久しぶりに仕事でASP.NET WebFormの新規プロジェクト作成。
bootstrap風になってからは初めてかも。
まず最初にWeb.sitemapを追加しSite.Masterの下記部分をメニューコントロールに切り替えようとしたらよもやの大はまり。
<div class="navbar-collapse collapse">
    <ul class="nav navbar-nav">
        <li><a runat="server" href="~/">ホーム</a></li>
        <li><a runat="server" href="~/About">詳細</a></li>
        <li><a runat="server" href="~/Contact">問い合わせ</a></li>
    </ul>
</div>
一層目だけならそれらしくなりました。
20170720001.png

<asp:Menu ID="Menu1" runat="server"
  DataSourceID="SiteMapDataSource1" CssClass="navbar-collapse collapse"
  DynamicMenuStyle-CssClass="dropdown-menu" StaticDisplayLevels="2"
  StaticMenuStyle-CssClass="nav navbar-nav" StaticSelectedStyle-ForeColor="#ffffff" StaticSelectedStyle-BackColor="#000">
  <StaticSelectedStyle CssClass="active" /><!-- これが効かない -->
</asp:Menu>
現在選択されているページのcssにactiveを追加したいのにselectedになったまま。仕方がないので StaticSelectedStyle-ForeColor="#ffffff"とStaticSelectedStyle-BackColor="#000"を追加しています。

二層目を追加すると、ウインドウサイズが小さくなるとデザインが崩れるので、面倒くさくなって人様のライブラリ入れてみようとTie.Controls.BootstrapをNugetで入れてみたところ、DataSourceIDを知らないと言われました。
旧プロジェクトの入れ替え用なので、Web.sitemap読んでくれないと困るんですわ。

確か家で一度やったはずなのにこんな時に限ってソース上げてないのでなぜ??と思って帰ってから確認したら、とても人様に晒せるようなソースではありませんでした(^^;)。
Menuコントロール使わずラベルに変え、Site.Master.csのPage_LoadイベントでSiteMapデータをぶん回してます。しかも文字連結でhtml作ってる突込みどころ満載なコードでとても後進に残せそうに無い感じ。ブログ用にそれらしい絵が欲しくて適当に書いた感満載。
とは言えこれをユーザーコントロールに変えるのが手っ取り早いのかも…。
SiteMap.CurrentNode.IsDescendantOf(node)までチェックしていて、子供が選択されていれば親にactive付くようになっているし。

2019/04/19
カスタムコントロール版をGitHubに上げました。

2016/11/28(月)ASP.NET WebFormでプラガブルなモジュール

やりたかったこと

プロジェクトを親子関係にして、親でナビゲーションを含むサイトデザイン、認証等、基盤となる仕事。
子プロジェクトは機能単位に分割。それぞれ他のプロジェクトをビルドすることなく追加、削除可能。
webform005.png

例えば赤枠の部分をそれぞれ別のDLLに切り離したい。ブログ追加するためにサイト丸ごとビルドし直したくない。
PHPなどスクリプト系の言語では当たり前の構造ですが、ASP.NETそれもWebFormでそれをやるとなると?

結論

コードを書かなくても(ヒントはここから貰ったわけですが)MEFとかUnity使わなくてもちょっと手間をかければできる(プログラマーとしてはあるまじき行為かも)。
本番プロジェクトでは未使用なので、どこまで使えるか不明(サービスの参照等すると、configの切り貼りが必要になりそうな予感)ですが、簡単なプログラムの統合なら使えそうです。

手順

  • 親プロジェクトを通常のWebFormアプリとして作成。Web.sitemapを追加しておく。
  • 親プロジェクトの直下に子プロジェクト用のフォルダ作成。子供の数が多くなりそうな場合は専用のフォルダ(Modulesにしました)作成。
  • ソリューションと一旦閉じてModulesの中に子プロジェクトを作成。ソリューション用のディレクトリは作成しない。テンプレートは空のWebサイト。作成したら一旦ソリューションを閉じる。
  • 親ソリューションを開く。既存のプロジェクトの追加で、上で作成した子プロジェクトを選択。
  • 子にSite.Masterを追加。ContentPlaceHolderのIDを親プロジェクトのIDと合わせる。例では親にデフォルトのWeb Formsサイトを使ったので、「MainContent」一つに。デザインはどうでも良い(実行時には親プロジェクトのSite.Masterが適用される)。
  • 子にSite.Masterを使ったWebFormを追加。最終的なプロジェクトの構成は下記のような感じ。
webform010.png

  • 子プロジェクトのビルドの出力先を、親プロジェクトのbinフォルダに設定変更後、子プロジェクトをビルド
webform020.png

  • 親プロジェクトのサイトマップに子プロジェクトのメニューを追加。親プロジェクトを実行。
webform030.png

  • 子プロジェクトのページもちゃんと親プロジェクトのヘッダとフッタがついて表示されます
webform040.png

  • お買い得品のページに認証かけてみたら、ちゃんとログイン画面へはじかれました。
webform050.png

OK キャンセル 確認 その他