DataGrid 操作についてメモ
DataGridTextColumn
セルのスタイルを編集する場合 DataGridTextColumn.ElementStyleを利用し、スタイルを指定する
<DataGrid> <DataGrid.Columns> <DataGridTextColumn Header="ヘッダー名" Binding="{Binding MyDate,StringFormat=yyyy/MM/dd}" Width="100"> <DataGridTextColumn.ElementStyle> <Style TargetType="TextBlock"> <Setter Property="TextAlignment" Value="Center" /> </Style> </DataGridTextColumn.ElementStyle> </DataGridTextColumn> </DataGrid.Columns> </DataGrid>
セルをカスタマイズ
DataGridTemplateColumnを利用し、DataTemplateを配置する
<DataGrid> <DataGrid.Columns> <DataGridTemplateColumn Header="ヘッダー名" Width="100"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <Button Command="{Binding ButtonActionCommand}" >押す/Button> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid>
編集可能セルを設定する
DataGridTextColumnでもIsReadOnlyがFalseの場合、ダブルクリックで編集可能だが、カスタムしたい場合、CellEditingTemplateを使用する。 ただし、表示時のTempleteも指定しないと表示されないため、CellTemplateも設定する必要がある。 ※DataGridTemplateColumnではCellEditingTemplateの中にバインドしたものだけが正しくSet処理が実行される。
<DataGrid> <DataGrid.Columns> <DataGridTemplateColumn Header="ヘッダー名" Width="100"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding Text1}" /> </DataTemplate> </DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellEditingTemplate> <DataTemplate> <TextBox Text="{Binding Text1}"/> </DataTemplate> </DataGridTemplateColumn.CellEditingTemplate> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid>
セルダブルクリックイベントをCommandで受け取る方法
DataGrid.InputBindingsにMouseBindingを設定し、イベントアクションをCommandにつなぐ
<DataGrid> <DataGrid.InputBindings> <MouseBinding MouseAction="LeftDoubleClick" Command="{Binding GridMouseDoubleClickCommand}"/> </DataGrid.InputBindings> </DataGrid>
ヘッダー表示をカスタマイズする。
HeaderTemplateを利用し、ヘッダーを2行表示する。
<DataGrid> <DataGrid.Columns> <DataGridTemplateColumn Header="ヘッダー名" Width="100"> <DataGridTemplateColumn.HeaderTemplate> <DataTemplate> <StackPanel> <TextBlock Text="ヘッダー1行" /> <Separator/> <TextBlock Text="ヘッダー2行" /> </StackPanel> </DataTemplate> </DataGridTemplateColumn.HeaderTemplate> </DataGrid.Columns> </DataGrid>
CSVファイルからのBULK INSERT
CSVファイルからSQL ServerのTableへ高速でデータを投入する
私用場面は色々あるが、とりあえず、スキーマ間でデータを移動する場合を想定します。
復元もとDBからデータを抽出するためのSQLをファイルに記載します。
output.sql
SET NOCOUNT ON ; SELECT * FROM [dbo].[MyTable];
コマンドラインからSqlファイルのSQLを実行し、CSVファイルに吐き出します。
SQLCMD -S localhost -U sa -P {password} -d {dbname} -i output.sql -s, -W -h -1 -o output.csv
出力されたファイルを復元先DBからアクセス可能なパスにおいてBulk Insertを実行します。
bulk insert dbo,MyTable from '\\c\work\output.csv' WITH ( FIELDTERMINATOR = ',', ROWTERMINATOR = '\n' );
ADO.NET Entity Data Model(edmx)で生成した接続文字列をコードで生成する。
ADO.NET Entity Data Model(edmx)で生成した場合
app.config内部にmetadataを含むConnectionStringが生成される。せっかく自動生成したEntity Data Modelを再利用しながら、ConnectionStringをConfigファイルから隠したいため、コードベースで生成する必要があった
DataContext修正
edmxの内部のDbContextクラスにDbConnectionをもらうコンストラクタを追加する。
Partial Public Class DbEntities Inherits DbContext Public Sub New() MyBase.New("name=DbEntities") End Sub ' 追加 Public Sub New(conn As DbConnection) MyBase.New(conn, True) End Sub End Class
追記:DALの更新時、追加したコンストラクタが消えてしまう事がわかったため、別のAppDbContextクラスで対応
Public Class AppDbContext Inherits DbContext Public Sub New(conn As Common.DbConnection) MyBase.New(conn, True) End Sub ''' ''' 以下の部分はDbEntitiesの自動生成プロパティをコピー・ペーストしてあげる。 ''' End Class
DBコネクション処理修正
' Initialize the connection string builder Dim sqlBuilder As New SqlConnectionStringBuilder() With { .DataSource = "localhost", .InitialCatalog = "testdb", .UserID = "sa", .Password = "mypassword", .IntegratedSecurity = True } ' Initialize the EntityConnectionStringBuilder. Dim entityBuilder As New EntityConnectionStringBuilder() With { .Provider = "System.Data.SqlClient", .ProviderConnectionString = sqlBuilder.ToString(), .Metadata = "res://*/DbModel.csdl|res://*/DbModel.ssdl|res://*/DbModel.msl" } _dbContext = New DAL.AppDbContext(New EntityConnection(entityBuilder.ToString()))
参考
Windows Server 2003, ASP.NET, IIS6.0
Windows Server 2003環境のIIS設定
仕事上、旧システムを動かしている現場があり、仮想環境に現状での移行をしてみたので、メモとしてやった事を記録する。
Windows Server 2003 R2のインストール
OSインストールCDは必要! 無料での入手は出来ない(公開されていない) サポートもとっくに切れている
.NET 2.0のインストール
.NET 2.0はMicrostのアーカイブから入手可能 https://www.microsoft.com/ja-jp/download/details.aspx?id=1639
IIS 6.0のインストール
当然ながら、Windows 2003なので、IISも6.0 インストールは以下の手順で行う
※途中からOSのCDを要求される。
- コントロールパネル
- プログラムの追加と削除
- Windowsコンポネントの追加と削除
- アプリケーションサーバー
- インターネットインフォメーションサービス(IIS)
ASP.NET AJAX 1.0のインストール
ASP.NET上でAjaxを使っている場合、AJAX Extentionsが必要となる。以下のURLから入手可能
https://www.microsoft.com/en-us/download/confirmation.aspx?id=883
ASP.NET 状態サービス
ログイン情報管理をASP.NET 状態サービスを利用する場合、Windowsのサービスから「ASP.NET 状態サービス」を起動する必要がある。
Google Home, IFTTT, Google Sheet, Slack連携
概要
Google Homeから最終的にSlackのチャンネルにポストするまでをためしてみた。 連携はIFTTTからGoogle Sheetへ書き込み、Google SheetからSlackへポストする流れとなる。
IFTTT連携(Google Home → Google Sheet)
My Applet タブから「New Applet」を洗濯
Triggerを設定するため「+this」を選択
Google Assistantを検索し、以下の画面から「Say a phrase with a text ingredient」を選択
Google Homeがトリガとするキーワードと読み取る文字列($)を指定、今回は「受付」をトリガーにその後の文字列を訪問者名として認識する設定
Triggerが終わるとAction指定のため「+that」を選択
Action処理としてgoogle sheetを選択
訪問者リストファイルのB2セルにトリガーで読み取った「$」が設定される様に設定
Slack連携(Google Sheet → Slack)
これまでの設定が問題なければ、「OK Google 受付 ○○○」で指定したGoogle Sheetに内容が記録されるはず。
訪問リストから、スクリプトエディターを選択し、以下のスクリプトを記載する。 (ソースは最後の参考URL本家のソースのそのままである。ただし、今後変更予定)
function showStatus() { var mySheet = SpreadsheetApp.getActiveSheet(); // シートを取得 var currentRow = mySheet.getActiveCell().getRow(); // 更新行を取得 var myCell = mySheet.getActiveCell(); // アクティブなセルの取得 if(myCell.getColumn() == 2) { //数字の部分には列番号(この場合B列) // 更新日時をA1に記録する var updateRange = mySheet.getRange('A' + currentRow); updateRange.setValue(Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy/M/d H:m:s')); var text = myCell.getValue() + '様が来訪されました'; slackPost(); // 更新行を記述するため1行追加 mySheet.insertRowBefore(2); } function slackPost() { var url = 'https://slack.com/api/chat.postMessage'; var token = 'xoxp-xxxxxxxxxxxxxx'; var channel = '#チャンネル名'; var username = '来訪通知'; var parse = 'full'; var icon_emoji = ''; var method = 'post'; var payload = { 'token' : token, 'channel' : channel, 'text' : text, 'username' : username, 'parse' : parse, 'icon_emoji' : icon_emoji }; var params = { 'method' : method, 'payload' : payload }; var response = UrlFetchApp.fetch(url, params); } }
※ Slack Tokenは以下のリンクから生成することが可能 https://api.slack.com/custom-integrations/legacy-tokens
最後に、Google Sheetのトリガーを設定する。 新しいトリガーとして、変更が発生したタイミングでshowStatusが実行される。
ここまで、問題がなければ、指定したSlackのチャンネルにポストされるはず。
参考
npmだけで、jQueryパッケージ管理
パッケージ管理を1つ集中する方法の一つとして、npmにより、jQueryを制御する
前提として、npm(node.jsのパッケージ管理)はインストール済み
npm init
対象プロジェクトフォルダでnpmを初期化する。
$ npm init
結果として、jsonファイルが生成される。
{ "name": "nvmtest", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC" }
jQueryのインストール
$ npm install jquery --save
node_modulesフォルダ作成され、中にjQueryがダウンロードされている。
scriptの作成
script.js
'use strict'; var $ = require('jquery'); $(function(){ $('h1').css('color','red'); })
1つのスクリプト内で、jQueryをrequireして利用しているため、1ファイルだけで、全てを完結できる。
Html
上記で作成した、scriptを指定するだけ
<script type="text/javascript" src="script.js"></script>
参考
ASP.NET MVC ページングを実装
ASP.NET MVC上でページングを実装する。
Nuget
以下のパッケージを追加 * PagedList.Mvc
Controller
簡単にリストモデルをPagedListで返す様にするだけ、 * pageパラメータから、ページ番号を取得する。(最初は1) * returnのViewにToPagedList(ページ番号, 表示行数)を返す。
using PagedList; public class HomeController { public ActionResult Index(string page) { int pageNo = int.Parse(page ?? "1"); List<MyModel> model = GetModelList(); return View(model.ç); } }
ViewModel
public class MyModel { public string Name {get;set;} public string Address {get;set;} }
HTML
View側のモデルをPagedListに設定する
Index.cshtml
@model PagedList.IPagedList<App.ViewModel.MyModel> @using PagedList.Mvc; <link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" /> <table class="table"> <tr> <th>Name</th> <th>Address</th> </tr> @foreach (var item in Model) { <tr> <td> @Html.DisplayFor(modelItem => item.Name) </td> <td> @Html.DisplayFor(modelItem => item.Address) </td> </tr> } </table> <br/> Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of @Model.PageCount @Html.PagedListPager(Model, page => Url.Action("Index", new { page }))
最後の2行は以下のようなイメージで表示される。
ページ番号をクリックするとIndexにpageが設定された形で次のページが呼び出される。
考えるところ…
EntityFrameworkをそのまま表示する場合、内部的に必要な部分だけ読み込んでくれるかもしれないが、 直接SQLを投げたりする場合は、このまますべて任せると全件読み取りになるため、パフォーマンス的には良くない。
ページング用のデータと、表示用のデータを別に実装したほうが良いかも
EntityFrameworkと連携する場合、もっと効率は良さそう
PagedList.IPagedList<App.ViewModel.MyModel> list; list = ef.users.ToPagedList(pageNo, pageSize);