WPF一覧

Caliburn.Micro に入門してみる その3

前回は簡単にバインディングができることを確認しました。実はあれは省略形に近いものだったので、フルに設定するとどのようになるかを今回確認します。
基本的に前回のプロジェクトの使い回しで説明します。

メソッド呼び出し

ボタンの Name を削除して、 Interaction.Triggers を指定してメソッドを呼び出してみます。

ShellView.xaml は以下のように変更します。

EventTrigger の Click までは問題ないとして、 Livet では CallMethodAction を呼び出していたような箇所で、 ActionMessage によってメソッドを呼び出します。
この ActionMessage も引数情報を設定することが可能です。パラメータを指定するには以下のようにします。

これを受け取るための IncrementCount メソッドでは引数を取れるように変更する必要があります。忘れると例外(No target found for method IncrementCount.)が飛びます。

メソッド呼び出し その2

ここまでの設定方法が Long Syntax と呼ばれるものになっているようです。次に Short Syntax と呼ばれるものについて確認してみます。

ShellView.xaml を編集してボタンを追加してみます。

見て分かるように、 cal:Message.Attach という添付プロパティでイベントとアクション(メソッド呼び出し)を設定しています。
注目なのはイベント名の記述と、メソッドの呼び出し&引数記述がこのように書ける、という点です。わかりやすいですね。

引数については即値で書いていますが、ここを他のコントロールの値にすることも可能です。

さらに Caliburn では、メソッド引数名から、引数を推測してバインディングしてくれる機能もあります。
以下のように ShellView.xaml を編集して、スライダとボタンを用意してみます。

スライダの名前を IncrementCount の引数名である delta としたことで、 Caliburn が情報をうまく解釈して結合してくれます。

まとめ

自分でバインディング設定を記述しないでもバインディングしてくれることで、プログラマの作業を省力化してくれる感がすごくあります。
ただし、ルールを知らないと動きを追いかけるのも厳しいという印象です。

これらのバインディングについては、 All About Actions を参照して読んでおくのもよさそうです。
パラメータとして、 $source, $view, $dataContext といったものも設定可能であったりするので、なかなか深いです。


Caliburn.Micro に入門してみる その2

前回はとりあえずプロジェクトを作成し、 Caliburn.Micro のお作法に従った Hello,world のようなものをやってみました。
今回はこのプロジェクトを使って、データバインディングを確認をしてみます。

今回も先人の記録を辿りつつ進めていきたいと思います。

ちなみに Caliburn.Micro の Documents の中では Basic Configuration 項にこの部分が書いてありますが、ほんの少しでした。

データバインディング

ShellViewModel に Count プロパティを追加します。

ShellView.xaml を以下のように編集してみます。

これを実行すると以下のようになります。明示的に「Text=”{Binding Count}”」 と書いていないですが、 Caliburn がこのバインド処理を行ってくれます。今回の場合、TextBlock の Name と対応するプロパティを見つけて、バインドを行う処理となっています。

コマンドバインディング

続いて以下のように ShellViewModel クラスにメソッドとプロパティを追加してみます。

そして、 ShellView.xaml も以下のように編集します。

これを実行して、 Increment ボタンを押すと、カウンタがインクリメントされ、 80 カウントになるとボタンが無効となります。

先ほどと同様にバインディングを記述していませんが、各コントロールの Name プロパティと一致するものを見つけて、バインドする処理が Caliburn によって行われるため不要となっています。Command の Can 系についても、同様に接頭辞 Can が付いたものを見つけて判定処理としてくれています。

余談

もちろん、Name を設定せずに Text=”{Binding Count}” などと記述することも可能です。 ValueConverter が必要なときには、こちらのような書き方をする必要が出てきそうです。


Caliburn.Micro に入門してみる

今まで MVVM のインフラストラクチャのライブラリとして Livet を使用していましたが、新バージョンも出ないし新しい環境用のプロジェクトテンプレートも提供が無いようだったので、比較的最近のものでよさそうなものは無いかと探してみたところ、Caliburn.Micro が良さそうだったのでこれを触ってみることにしました。

ここでは、 Nuget から簡単にインストールができる Caliburn.Micro バージョン 3.2.0 を対象にしています。また Visual Studio は 2017 (v15.6.1) を使用しています。

Caliburn.Micro について

Caliburn.Micro は出たばかりというわけでなく、5年以上経過しているというのに、日本語での記事がほぼないです。これから MVVM アーキテクチャでソフト開発を始めようと思っている人には、 Livet のほうをオススメできるのではないかと思います。 Livet のほうが日本語での検索性は良いです。

Caliburn のほうが良い点としては、対応プラットフォームが Livet よりも多いこと、現在も開発が続いていることが挙げられると思います。また、現時点においては開発者の方は Microsoft にいるらしいです。近いうちに、バージョンが 4.0 が出そうです。自分は Livet の良かった点に、プロジェクトテンプレートやらスニペットの準備やら、始めるのに楽だった点があります。 Caliburn.Micro ではそのような点は標準ではなさそうですが、普段のコード書きを楽にしてくれそうなバインディングの仕組みを提供してくれています。そして、 MEF を用いた拡張しやすそうな構成も1つの魅力に感じました。
続きを読む


WPF の ListView で選択項目を中央にしたスクロール制御

ListView で選択された項目をコントロールの中央に表示したいと思うことがあります。今回はこれを実現するべく実装を考えてみました。考え方としては ListView が持っている ScrollViewer を制御して、スクロールを制御することにしました。

結果

実装した結果を示します。作成したアプリの動きとしては次のようになっています。

  • 選択状態にあるものを画面外にスクロールさせたとして、”アジャスト”ボタンを押すと、その項目が中央になるように表示
  • 項目の番号を指定して”選択”ボタンを押すと、対象の項目を選択状態にして、その項目が中央になるように表示

続きを読む


ListView での VerticalContentAlignment バインディングエラー

ListView(+ListViewItem) のスタイルをいじってバインディングのエラーが出るのは分かるのですが、予期しないところでエラーが出るので困っていました。今回、ひとまずどういったときにエラーメッセージが出るのかが掴めたのと、今後同じように悩まないためにもメモとして残しておこうと思います。

バインディングエラーと対策

ListView あたりのスタイルをいじっていて以下のようなワーニングメッセージを見ることがありました。特にこの辺りのバインディングいじっていないのに出てしまうので疑問に思っていましたが、起因しているものが分かりました。

このエラーメッセージは、内容が動的に変化するコントロールにおいてよく出るようです。自分の場合には ListView などで仮想化して使っている場合に、このような症状が出るようです。

そこで ListViewItem のプロパティセッターに以下のようにしてパラメータをセットするようにして解決できました。

仮想化ありの場合

仮想化ありの場合においては上記の設定でうまく出来ませんでした。 ListViewItem の中身をカスタムする時に、 Blend を用いて既存のものをコピーして、編集する方法で行いましたが、当初のようなエラーメッセージを見ることになりました。

対策としては以下のように編集しました。

ListViewItem のテンプレートを Blend を用いて既存のものをコピーして作った場合、上記の(※)の部分についてもバインディングが設定されています。しかしそれにより今回のようなバインディングエラーが通知されてしまうため、項目そのものを削除しました。

まとめ

この手のものは、他にも動的な右クリックのメニュー(コンテキストメニュー)を作っているときにも、出遭いそうな気がします。参考情報を見ると、 WPF での既知の問題といえる内容にも見えます。

参考情報


WPF と OpenGL の空域問題への対処

WPF を使っていて厄介な問題の1つに空域の問題があります。特に DirectX や OpenGL, Vulkan といった HWND を使うものを扱って WPF の世界に持ち込むと遭遇します。他にも HWND を必要とする(従来型の)コントロールを配置すると出遭います。ブラウザのコントロールなどが該当するようです。

具体的には HWND を使用したコントロールを配置、ホストすると、その上には WPF のコントロールを配置できません。配置してエラーになるというわけで無く、 HWND のコントロールが最前面に来てしまうため見えない状態となってしまいます。

今までは、描画結果を D3DImage や Image など画像にしてしまって配置する方法を考えていましたが、もっと別の手段があるようだったので試してみることにしました。

続きを読む


WPF TreeView with SelectedPath binding

Windows エクスプローラーが備えているフォルダツリーのようなものを、 WPF を利用している自作アプリケーションで使用したいことがあります。
調べてみるといくつかの実装が見つかりますが、フォルダツリーの実現のためにビューモデルとビューが分離されている本気度の高いものが多く、もう少し手軽なものがないかなと思った次第です。

以前に以下のアドレスで公開されていた方式が割と気に入っていたのですが、現時点においてアクセスが出来なくなってしまいました。
http://khmylov.com/blog/2010/11/wpf-explorer-treeview-with-selectedpath-binding/

ちょっとしたときにはこれで十分だったりしてお気に入り実装だったので、元の記事を自分なりに再解釈してみたいと思います。

続きを読む


WPF で描画結果を画像ファイルへ

GDI のメモリ DC で書いたオフスクリーンの内容で画像ファイルを作成するという方法はよく知られていると思います。これを WPF ではどうするのだろうと思って試してみました。

描画

まずは画像作成元となるものを作ります。 WPF では RenderTargetBitmap というクラスがあり、これを使うと保持している内容をビットマップとして取得が出来ます。
ただ、この RenderTargetBitmap に対して直接、直線や円を描く、というものではありません。Canvas オブジェクトを使って、Canvas に中身を描いて、この Canvas を RenderTargetBitmap にセットするというのが手軽に図形を描画する方法といえそうです。

続きを読む


WPF TreeView の破線描画付き その3

もうすこし TreeView の見た目に足掻いてみました。
今までのものは項目の部分でクリックが有効になるのですが、 Windows エクスプローラーなどではその行で選択できるようです。
これを実現してみようとトライしてみました。

結果

現時点の実装状態ではこんな感じが出来ています。

実現方法

通常のものだと TreeViewItem の要素は 田 の形で区切られて、右下の部分にさらなる子供のデータを表示するという実装になっています。
親から子供まで行をフルに選択させつつ見た目は従来通り、ということを実現するためにはこの方法を変更する必要があります。

では、どう実現するかですが、ここでは子供の深さ分を横にスライドするという方法を行ってみました。現在の深さからマージンを返すコンバーターを用意して、この実装としました。

今回のこの実装もまた GitHub のほうにおいてあります。
https://github.com/techlabxe/TreeViewCustomized2


WPF TreeView で破線付きを作ってみた その2

先日の続きの話になります。
TreeView の階層構造を破線でつなげて描画したものにするといったネタになります。

TreeView 本体ではなく、 TreeViewItem のテンプレートを編集して以下のようなものが実現できました。

標準のテンプレートで変更した箇所と言えば、開閉のための三角を+や-に変更したところでしょうか。
未使用の列については破線を描くために Rectangle を配置しています。

また今回の産物は GitHub のほうで公開してみることにしました。
何かの参考になったり、不具合の修正など提案して頂けたら幸いに思います。

https://github.com/techlabxe/TreeViewCustomized