(小ネタ)WindowsフォームのDataBindingに関するリンク集
Windowsフォームでデータバインディングを行う場合に、BindingSource、IDataErrorInfo、ErrorProvider、null値の制御についての有用なリンク集。
サイト
WindowsFormsでの単項データバインドまわり | tocsworld
IDataErrorInfo Interface (System.ComponentModel) | Microsoft Docs
双方向データバインドによる単体入力エラーチェック – とあるコンサルタントのつぶやき
書籍
BindingSourceを使用したTextBoxのデータ入力時におけるメリット
以前にWindowsフォームで作成したアプリケーションを修正する機会があり、BindingSourceについて理解が深まったので、記録を残しておく。
「TextBoxに入力した値をバリデーションして、正しい値ならば紐づいたDBのレコードを更新する」というよくある処理を実装する場合、BindingSourceを使用してBindingを行うと以下のようなケースで便利だった。
バリデーションでエラーになったら、変更前の値を復元したい
バリデーション処理は、Validatingイベントを使用すると思うが、パラメータから取得できる値、TextBoxフィールドの値も変更後の値になっている。
このままでは変更前の値を取得できないため、変更前の値を格納するフィールドを用意すると思うが、実はBindingSourceを使っていると変更前のフィールドがいらなくなる。
それは、BindingSourceから名前付きDataRowを取得でき、それが入力前の値を持っているからだ。名前付きDataRowの取得、入力前の値の取得は、以下のように行う。
var dataRowView = bindingSource.Current as DataRowView; var row = dataRowView?.Row as 名前付きDataRowクラス名; if (row != null) { originalText = row[nameof(row.プロパティ名), DataRowVersion.Original].ToString(); } //originalTextを使用して変更前の値を代入する処理など
レコードを更新する時に、値が変更されている場合のみ更新したい
バリデーション後の更新では、Validatedイベントを使用すると思うが、値が変更されていないのに毎回DBに接続して更新するのもムダなので、値が変わった場合のみ更新をしたい。
DBから取得した値と比較する方法があるが、対象が1つの画面からしか更新されない場合、取得のために毎回DBに接続すると、DB接続回数が増えてしまう。
上記の変更前の値を使用して、入力値と比較する事もできるが、実はBindingSourceを使っているともっと簡単な方法がある。
それは、BindingSourceから取得できる名前付きDataRowが、変更情報を持っているからだ。変更されたかどうかの判定は以下のように行う。
//rowは、名前付きDataRowクラス名のインスタンス。取得方法は上記と一緒。 if (row.RowState == DataRowState.Modified) { //データが変更された場合に行う処理(DB更新処理など) }
以上。
NPOIでExcelのセルの値を取得する(関数も対応)
NPOIを使用してExcelを読み込む処理を作成したので、後から見返せるように気づいたことをメモしておく。
確認したバージョン:.NET Framework 4.6、NPOI 2.3.0
Excelのセルの値を取得する場合は、以下のようにまずICellインスタンスを取得する。
//sheetは、ISheetインターフェイスのインスタンス
ICell cell = sheet.GetRow(行番号).GetCell(列番号);
数値や文字列を取得する
ICellインターフェイスで宣言されているプロパティから値を取得することが出来る。セルが空の場合も対応している。
ICellインターフェイス
やりたい事 | プロパティ | セルが空の場合の返り値 |
---|---|---|
数値を取得する | NumericCellValue | double型の0 |
文字列を取得する | StringCellValue | string型の""(空文字) |
関数の結果を取得する
NumericCellValueプロパティや、StringCellValueプロパティは、セルの値が関数の場合、関数を評価した結果を返してくれる。
ICellインターフェイス
やりたい事 | プロパティ | 関数の場合の返り値 |
---|---|---|
数値を取得する | NumericCellValue | 関数を評価した結果の数値 |
文字列を取得する | StringCellValue | 関数を評価した結果の文字列 |
関数を評価した結果を取得するのに、IFormulaEvaluatorインターフェイスを使用する方法もある。
Evaluateメソッドに対象セルのICellインスタンスを渡して実行し、CellValueインスタンスを取得する
//workbookは、IWorkbookインターフェイスのインスタンス IFormulaEvaluator evaluator = workbook.GetCreationHelper().CreateFormulaEvaluator(); //cellは、ICellインターフェイスのインスタンス(値を取得したいセル) CellValue cellValue = evaluator.Evaluate(cell);
CellValueインスタンスに関数の評価結果が入るので、プロパティから値を取得することが出来る。
セルの値が空の場合は、CellValueインスタンスにnullが入るため、プロパティを参照すると例外が発生する。
CellValueクラス
やりたい事 | プロパティ | セルが空の場合の返り値 |
---|---|---|
数値を取得する | NumberValue | NullReferenceExceptionが発生 |
文字列を取得する | StringValue | NullReferenceExceptionが発生 |
CellValueクラスでは、関数の評価結果のデータ型とプロパティが異なっていても例外にはならない。
CellValueクラス
関数を評価した結果 | プロパティ | 返り値 |
---|---|---|
数値 | NumberValue | 数値 |
数値 | StringValue | null |
文字列 | NumberValue | double型の0 |
文字列 | StringValue | 文字列 |
関数を評価した結果のデータ型が、条件によって変わるセルの値を取得する
ICellインターフェイスのプロパティでは、関数の評価結果とプロパティの型が異なると例外が発生するため使えない。
ICellインターフェイス
関数を評価した結果 | プロパティ | 返り値 |
---|---|---|
数値 | StringCellValue | InvalidOperationExceptionが発生 |
文字列 | NumericCellValue | InvalidOperationExceptionが発生 |
関数を評価した結果の型が条件によって変わる場合は、CellValueクラスを使用する。
CellValueクラスのCellTypeプロパティにはデータ型が格納されているため、データ型で分岐して処理が出来る。
//cellValueは、CellValueクラスのインスタンス var value = string.Empty; if (cellValue.CellType == CellType.String) { value = cellValue.StringValue; }
以上。
jQueryのfloatTheadプラグインを使用したテーブルを印刷する方法
少し前ですが、レコード数の多いテーブルを表示した時に、スクロールでExcelみたいに先頭行を固定して表示したい時に、jQueryのfloatTheadプラグインを使用しました。*1
さらにfloatTheadプラグインを使用したテーブルを印刷したいという要件が出た時に、そのままでは印刷レイアウトが崩れてしまったので、対処方法を調べました。
作者のGitHubのissueページに載っていました。
Support for printing tables · Issue #68 · mkoryak/floatThead · GitHub
内容を大まかにまとめると、 メディアクエリを使用してブラウザ表示か印刷かを判別し、 印刷の場合はtable要素のfloatThead('destroy')を呼び出し、 画面表示に戻ったら再度table要素のfloatThead()を呼び出す。 という感じです。
以上
Hyper-V で Vagrant
この間、Hyper-Vで仮想環境を構築しているので、せっかくだからVagrantも使ってみることにした。
動作確認環境は以下の通り
実際にやってみたところ、特につまずく箇所もなく、起動に成功した。ファイアウォールの設定はしていないため、フォルダ共有が出来なかったくらい。既定のスイッチ周りはどうなるかが気になっていたが、接続しているようだ。
行ったことをメモしておく。
- Vagrant のインストール
- Vagrant Box の取得(Box は hashicorp/precise64 を使用)
- Vagrant テスト用のフォルダを作成して移動
- vagrant init 実行
- vagrant up 実行(provider として、Hyper-V を指定)
- vagrant ssh で接続
- vagrant halt で停止
Vagrant のインストール
Vagrant公式サイトで、Windows 64-bitをダウンロードして実行した。
Vagrant Box の取得
Hyper-Vな点だけ注意して、以下のコマンドを実行すると、Vagrant Box の取得が出来た。
vagrant box add hashicorp/precise64 --provider=hyperv
Vagrant テスト用のフォルダを作成して移動、vagrant init 実行
Vagrant テスト用のフォルダを作成して移動し、以下のコマンドを実行した。
vagrant init hashicorp/precise64
vagrant up 実行(provider として、hyperv を指定)
Vagrant Boxと同様にprovider にHyper-V を指定した。仮想マシンの本体は、vagrant upを実行したフォルダに作られる.vagrantフォルダ以下に保存された。
vagrant up --provider=hyperv
vagrant ssh で接続、vagrant halt でサーバ停止
正常に動作した。vagrant status コマンドで停止したのも確認できた。
その他
初期設定では、個人フォルダ配下の.vagrant.dフォルダにBoxファイルが配置されるので、以下を参考にして配置場所を変更した。
以上
IISのApplicationPollIdentityとWindows認証によるDBアクセスで発生したエラー
新年あけましておめでとうございます。今年もよろしくお願いします。
さて、ASP.NET MVC の権限関係では、いくつか記事を書いた。
上記を参考にすれば、躓かずに構築できると思ってたが、あまり見たことのないエラーに遭遇したのでエラー内容と解決策を記録しておく。
実行環境(ただし、今回はあまりバージョンは関係ないと思う)
- Windows Server 2016
- IIS 10
- SQL Server 2017(IISと同一サーバにインストール)
- ASP.NET MVC 5.2.3
- Entity Framework 6.1.3
設定や前提条件
- IIS上に複数サイトを作成して、ドメイン名によってサイトへの振り分けを行っている
- サイトではなくアプリケーションで、Windows認証を有効にしている
- アプリケーションプールはApplicationPollIdentityを使用。アプリケーションプールユーザにDBアクセスの許可を設定している
- アプリケーションからDBへのアクセスは、Windows認証
遭遇したエラーメッセージ
System.Data.Entity.Core.EntityException: 基になるプロバイダーが Open で失敗しました。 ---> System.Data.SqlClient.SqlException: ログインできませんでした。このログインは信頼されていないドメインからのログインなので、統合認証では使用できません。
あまり見たことが無いエラーなので、DBアクセス許可の設定をやり直したり、Windows Serverの再起動をしてもらったりしたが、変化なし。
エラーメッセージで検索しても、めぼしい情報は見つからず。
落ち着いて考えるとメッセージは、(権限による)アクセス許可の問題ではないと思いたち、今までと違う所を探した。
そうすると、DBの接続文字列が違っていた。今まではサーバー名を設定していたが、今回はDNSに設定したドメイン名を使用していた。接続文字列をサーバ名に戻すと、エラーが発生しなくなった。
対処方法
Data Sourceにサーバー名を指定する。
以上。
2018年にもっとも読まれた記事ランキング
しばやん( id:shiba-yan )さんが作った「2018 年の人気記事ランキング生成」を使わせてもらい、記事ランキングを作成してみました。
ランキング自体は、右下の注目記事と大差ないですね。ランキングにしめる2015年、2016年の記事の割合が相変わらず高いです。 ブログを始めたのが、2015年で当初は色々とネタがあったという事でしょうか。
(小ネタ)WindowsフォームでShowDialogメソッド、Showメソッド、Closeメソッド、Disposeメソッドの動作を理解する。
(小ネタ)Visual Studio 2015 のバージョンがv14なわけ。(Visual Studio 2013 はv12です)
来年も地道に続けていこうと思います。