WPFとVBでアプリ作る準備その4、コントロールを重ねた時の上下移動(ZOrder)はPanel.SetZIndex
前回は昨日
の続き
コントロールを上下に重ねた時の位置関係を指定する
WPFではZIndexプロパティで指定する
テスト結果

選択画像のZ位置をボタンで変更
ZIndex(上下の位置)を指定しない場合

ZIndex(上下の位置)を指定しないと最初に配置したものが一番下になって
後に配置したものが上に重なっていく

ここからbutton1のZIndexを1にすると

拡大

ZIndexを文字で指定するときはPanelを付けて
Panel.ZIndex="1"とかになるみたい。
大きい数値が指定されたものほど上に表示される
マイナスの数値も指定できる
同じ数値の者同士なら後に設置されたものが上になるbutton1をクリックしたらZIndexを1に変更するをVBのコードで書く場合
デザイン画面

button1をダブルクリックすると


Panel.SetZIndex(sender, 1)
これでbutton1のZIndexが1になる
senderはクリックイベントを起こしたbutton1自身
実行して

button1をクリックすると

ZIndexを指定するときは
Panel.SetZIndex
ZIndexを取得するには
Panel.GetZIndex
Windowフォームアプリだと最前面か最背面の指定しかできなかったので
ひとつ上か下に移動したい時でも全コントロール数の半分を移動させる必要があって
それに比べるとWPFのSetZIndexはかなり便利
エクセルVBAでも最前面、最背面、ひとつ上、ひとつ下へ移動させるっていう便利なのがあるんだよねえ
上下の表示位置の指定はだいたいわかったので
ZIndexを指定する画像はどれなのか判別できるように
選択中の画像を表示する見本画像を用意
選択中の画像をひとつ上、ひとつ下へ移動させるボタン
選択中の画像のZIndexを表示するTextBlock
などを用意して
デザイン画面はこうしてみた

これをそのまま貼り付けて記事を投稿するとエラーになってしまうことが多い
<>がいっぱいあるのが良くないのかなあ
投稿はできたようにみせかけて投稿した記事を見るをクリックすると
記事が見つかりませんというエラー
なので実質全部書き直しになるし確認ボタンでのプレビューでは問題ないから
怖くてできないので画像だけ
それぞれの画像のZIndexは0から順番につけて同じ数値がつかないようにしたい
なので画像が全部でいくつ表示されているのかとかまとめて取得しておきたいので
Pixtack紫陽花の時と同じCollectionのList(Of Image)を使ってみたんだけど
ググっていたらいいのがあった
ObservableCollection
これ
Itemの移動させるMoveメソッドが今回の目的にピッタリ
中に入れたItemにはIndexが0から順番についていくので
この番号をZIndexに合わせればいいなと
Moveメソッドで移動させたらIndexも変化するので
そのIndex番号をSetZIndexで使えば一石二鳥な感じ
なのでこのObservableCollectionを継承したクラスを作成
作成場所は前回作ったExImageクラスと同じ場所にしてみてこうなった
画像
32行目から最後までが今回書き加えたところ

ObservableCollectionを継承して、ExImageクラスを入れることにした
Itemを移動した時についでにZIndexを指定したいので
MoveItemメソッドをOverridesしてそこに処理を書く

MoveItemを選択してタブキー押すと

動かしている時の中の様子

OldIndexが元の番号でNewIndexが移動先の番号
画像が3つ入っている時に0番を1番に移動しようとしている時の様子
これはそのまま問題なく処理が進む
問題になるのは移動先の番号が範囲を超えてしまう時
-1以下や3以上だと場所がないのでエラーになる

これは指定された移動先が-1になっている、Indexは0,1,2のどれかで
-1番はないからエラーになるので対処
MyBase.MoveItem(oldIndex, newIndex)
この部分が実際のItem移動の処理の部分だと思うから、この直前で
If newIndex >= Count OrElse newIndex < 0 Then Return
範囲外だったら処理前に終了(Return)
SetZIndex(Item(oldIndex), oldIndex)
SetZIndex(Item(newIndex), newIndex)
移動が終わったらSetZIndexで画像(ExImage)の表示位置の移動
移動させるってのは隣と入れ替わるってことだから
自分自身と隣の画像の両方のZIndexを指定する
MainWindowのVBコード

主に書き加えたのは58行目
その他書き加えたところは

これを書いておくと今回多用する
Panel.SetZIndexやPanel.GetZIndexを
SetZIndexやGetZIndexと書くだけで済むようになる
けど今見なおしたらあんまり書いてなかったw

クリックした画像(ExImage)を記録しておく用
このExImageを上下移動させる、見本表示にも使う
9行目
全画像を入れておくリストコレクションを作成
ObservableCollectionクラスを継承して作ったObservableCollectionExImageを
作成、これに全部の画像(ExImage)を入れる

ObservableCollectionExImageに入れる
36行目、作成したExImageのZIndexを指定
指定する数値はリストコレクションに入っているItemの数-1
42行目:ExImageのMouseDownイベント発生時に動かすメソッド
ExImage_MouseDownを指定
このメソッドは77行目

クリックした画像をFocusExImage変数に入れる
デザイン画面で作っておいた見本用のmihonのSourceにクリックした画像を
指定して見本画像を表示する
80行目
デザイン画面で作っておいたTextBlockの表示更新

選択画像を上下させる部分

64:選択画像のIndex番号を取得
65:リストコレクションのMoveメソッドでItemを移動
第1引数が移動させたいIndex、第2引数が移動先のIndex番号
ひとつ上に移動だから1を足している
66:TextBlockの表示の更新は58行目へ

画像ファイル4つをドロップして表示して
一番下にある緑の画像を選択したところ
一番下なのでZIndexは0
ここからageボタンを押すと

ひとつ上に移動して黄色画像と入れ替わる
ZIndexも1になっている
予定しているテスト、上の3つは必要な機能
- 表示画像すべてを画像ファイルとして保存
- ドラッグ移動時に指定ピクセルごとに移動
- 指定した画像の表示を消す(削除)
- 指定した色を透明にする
- レイアウト
完了したテスト
- 画像ファイルドロップで画像表示
- 画像をマウスドラッグで移動
- 表示画像のレイヤー間の移動(入れ替え)ZOrder指定←New
参照したところは
汎用ジェネリックコレクション その2 ObservableCollection/ReadOnlyObservableCollection (System.Collections.ObjectModel) - Programming/.NET Framework/コレクション - 総武ソフトウェア推進所今回のテストはこことObservableCollectionのおかげでかなり満足行くできになった
http://smdn.jp/programming/netfx/collections/3_objectmodel_2_observablecollection/
Pixtack紫陽花のときはFor~Nextでぐるぐる回していたからCPUの占有率も上がっていただろうし、コードの量も2倍以上はあったなあ
今回の記事の続き
WPFとVBでアプリ作る準備その5、スクロールバーの表示、回転とかの変形後のコントロールのサイズ取得 ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
http://blogs.yahoo.co.jp/gogowaten/13919066.html