Hatena::ブログ(Diary)

周回遅れのブルース

2017-03-16 WPF TIPS

Q128. IE ベースでない Browser コントロールは存在しないか

| 13:30 | Q128. IE ベースでない Browser コントロールは存在しないかを含むブックマーク

A.昨日のエントリでは WPFWebBrowserコントロールについて書きました。これ IE7という非常に旧いバージョンをベースにしてるので、ページによってはレイアウトが大きく崩れます。それを回避するのがレジストリ編集な訳なんですが、標準コントロールにも関わらずそこまでしなきゃいけないのは、なんとも気持ち悪すぎます。何とかならんかということで、WebBrowser 以外の Browserコントロールを探したところ、一つ面白いのが見つかりました。

DotNetBrowser というChromium ベースのBrowserコントロールが TeamDev 社から提供されてたので、早速これを試してみたいと思います。

DotNetBrowser

f:id:hilapon:20170316132611p:image:w500



続きを読む

matarillomatarillo 2017/03/25 18:12 CefSharp http://cefsharp.github.io/ や Awesomium http://www.awesomium.com/ なんてのもありました。前者はOSSで無料ですが、Acid3だと99点になってしまいました……

hilaponhilapon 2017/03/27 10:47 情報ありがとうございます。機会みて試してみたいと思います。

2017-03-15

Q127. WebBrowser コントロールの IE のバージョンを最新にしたい

| 11:13 | Q127. WebBrowser コントロールの IE のバージョンを最新にしたいを含むブックマーク

A.WPFWebBrowser コントロールのIEのバージョンが 7 なのは有名なようですね。現状ではレジストリを編集するしか手はないようです。以下の記事では、レジストリの編集方法を紹介されてます。


関連記事:WebBrowser コントロールで使われている Internet Explorerを最新のバージョンに変更する

関連記事:WPFのWebBrowserで使用されるIEのバージョンを最新にする


しかしレジストリをいちいち編集するのは気が重いし気持ち悪い。もうちっと何とかならんものかねぇ。。。


WPF FAQ の目次に戻る

 

2017-03-03 WPF FAQ

Q124. XamDataGrid で絞り込み表示されてるレコードのみ抽出する(其の弐)

| 15:26 | Q124. XamDataGrid で絞り込み表示されてるレコードのみ抽出する(其の弐)を含むブックマーク

A.以前のエントリで、XamDataGrid で絞り込み表示されてるレコードのみ抽出する方法を紹介しましたが、これ一つ落とし穴がありまして、要素の描画タイミングによるのか、正常にレコードを取得できない場合があったりします。

関連記事:Q124. XamDataGrid で絞り込み表示されてるレコードのみ抽出する


例えば、XamDataGrid でフィルタリング実行時のイベント内で、絞り込まれたレコードのみ抽出したい場合、こんなコードになるかと思います。


レコード数やフィールドの少ない簡単な画面ならこれでも問題ありません。ところがレコード数が多かったり、フィールドが多いと、実際の表示と返されるレコードが異なる場合があることが判明しました。恐ろしいですね(汗



Dispatcher を使ってみる

この現象、どうやらレコードやフィールドが多すぎるか、ビューが複雑だと、フィルタリングと要素の描画更新のタイミングがずれるため発生するように思えます。そこで Dispatcher を使い、要素の描画とレコードの取得を同期するようタイミングを調整してみました。


これで、表示されてるレコード数とプログラム内で処理するレコード数の同期は取れました、ただし、状況により恐ろしい事態が発生します。フィルターのテキストボックスに文字列打ち込んでると、たまに

別のユニットが既に開いている間は、undo ユニットを再度開くことはできません。

と、InvalidOperationException 例外を吐いて、アプリケーションがクラッシュします。.NET Frameworkソースコード追っかけると、UndoManager の Reopen メソッドで例外起こしてるのですが、恐ろしいですね。危険極まりないので、やみくもに Dispatcher を使うのは止めましょうw


RecordFilter.ApplyPendingFilter メソッド

そこで散々調べた結果*1RecordFilter.ApplyPendingFilter メソッドを使えば、安全にフィルターの変更をビューに適用できることが判りました。以下、修正したコードです。


RecordFilter.ApplyPendingFilter の解説を読むと、

フィルターの保留中の変更を適用します。

としか書いてないしネットの情報も殆どないので、何のこっちゃ?と思ってたのですが、今回初めて使ってみました。果たしてこれが本来の使用方法かどうか怪しいのですが、とりあえず正常動作してるので、まあ良しといたしましょう(汗




WPF FAQ の目次に戻る


 

*1:ネットも情報ないのでヘルプやらソースコードやらサンプル作って試すやらetc・・・

2017-02-25

Q126. XamDockManager のレイアウトを保存・読み込み・初期化したい

| 13:48 | Q126. XamDockManager のレイアウトを保存・読み込み・初期化したいを含むブックマーク

A.XamDockManager はペインを一元管理できるコントロールでして、ペインのドッキングやフローティング、タブや左右・上下の配置などを自在に配置可能なコンテナコントロールです。Visual Studio のIDE をイメージすれば判りやすいと思います。

f:id:hilapon:20170225133829p:image:w300


ユーザーがペインを自由に配置できるとあれば、当然レイアウトを保存・読み込みしたいというニーズも出てきますね。XamDockManager ではレイアウトの保存・読み込みに LoadLayoutSaveLauout・というメソッドが用意されてます。


サンプルコード

以下、簡単なサンプルを用意しました。XamDockManager のレイアウトの保存・読み込み・初期化するサンプルです。以下の画面は上の画面と同一のものですが、クライアントがレイアウトを変更したものになります。

f:id:hilapon:20170225133828p:image:w300


まずビューです。


お次はコードビハインドです。LoadLayout・SaveLayout の両メソッドで簡単に設定できるのが理解できると思います。レイアウトの状態をファイルに保存するには、オーバーロードされたメソッド(ストリームをパラメータで扱うバージョン)を使えば、簡単に保存できます。


初期化に関しては XamDockManager 側でメソッドが用意されてないため、ContentRendered イベントで要素が初期化されたタイミングを見て、SaveLayout メソッドで初期状態を保存。初期化ボタンクリック時に LoadLayout でXML文字列を読み込んでます。


WPF FAQ の目次に戻る


 

2017-02-18 WPF FAQ

Q110. XamDataGrid でユーザーが設定したレイアウトを保存したい(其の参)

| 15:14 | Q110. XamDataGrid でユーザーが設定したレイアウトを保存したい(其の参)を含むブックマーク

A.以前、XamDataGrid でユーザーが操作した列の移動や並び替え、グループ化やソートを次回起動時用に保存したい場合、SaveCustomizations メソッドやLoadCustomizations メソッドを使えば、レイアウトの保存・読み込みが可能だという記事を公開しました。

関連記事:Q110. XamDataGrid でユーザーが設定したレイアウトを保存したい


しかし記事の最後に書いたとおり、ClearCustomizations メソッドでフィールドを初期状態に戻そうとすると

  • フィールドの表示状態を初期化できない
  • フィールドの固定がリセットされてしまう

という問題が発生するため、昨日のエントリでは、その対処としてコンストラクタでフィールドの状態を保存し、ClearCustomizationsメソッド実行後、LoadCustomizations メソッドで表示と固定列を初期化する方法を紹介しました。以下、その対処法の記事になります。


関連記事:Q110. XamDataGrid でユーザーが設定したレイアウトを保存したい(其の弐)


カスタムXamDataGrid

上記で一見解決できたように思えましたが、複雑なUIに配置されたグリッドや、TabItem に配置され起動時に非表示になってるグリッドは、コンストラクタや 画面のContentRendered イベント、いや XamDataGrid のOnRender でもフィールドが生成されてない場合があり、列情報を取得できないことがあることが判りました。

結局、DataPresenterBase.FieldLayoutInitialized イベントの通知後でないと、フィールドの初期状態を正確に取得することはできない模様です。

そこで Window のコードビハインドでいちいちイベント書くのも煩わしいため、XamDataGrid をカスタマイズした方が早いという結論に達しました。それがこちら。


コントロールの継承って好きじゃないですが、今回のケースでは止むを得ません。以上、何かの参考になりましたら幸いです。



WPF FAQ の目次に戻る