• 車種別
  • パーツ
  • 整備手帳
  • ブログ
  • みんカラ+

元)零細社長のブログ一覧

2007年11月28日 イイね!

【C#】ListViewに自作コントローラーをぶら下げる【.NET3.0】

.NET3.0のコントローラーはUIElementという抽象化クラスで扱えることになっているのでなんでもサブクラス化できる。
ドロップダウンリストにImageがそのままAddできちゃったときはおしっこ漏らしそうなほどびっくりしたものだ。

ちょっとこれ.NET2.0でやったら3日はかかるんですけど(゚Д゚)

ならば
TreeViewにもImageやボタン、はては自作コントローラーもAddできるんでない?



まずは配列を作らなくてはいかん。
ObservableCollectionで自作コントローラーの配列を作ってTreeコントローラーにバインドしてみた。
すると確かに自作コントローラーが並んだ。
しかし階層化されない。
そりゃそうだ。
しかしどうやって・・・。うーむ。

まずは
例によって文献が超少ない中頑張って調べた。どうもHierarchicalDataTemplateというテクニックを使うといいらしい。
ここにサンプルがある(日本語版だとなぜかサンプルプロジェクトのリンクが切れてる)。

サンプルでは
親クラス
コドモクラスの配列(List)
名前


コドモクラス
孫クラスの配列(List)
名前


孫クラス
名前


と用意されていて、大元クラスが親クラスをメンバーとして保持。
コンストラクタで親・子供・孫と、適宜追加している。
なるほど。

で、XAMLでDataTemplateではなく、HierarchicalDataTemplateとしてリソースを作っている。
親・子供・孫それぞれ定義している。
コードを見ると、ItemsResourceのところに、保持する配列のクラスが定義されていることが分かる。
なるほど。

さらにいろいろいじって分かったこと
HierarchicalDataTemplateを定義する方法はXAMLを直に書くしかない。
階層クラスは子供・孫と用意する必要はない。自分をメンバー化すれば再帰的に階層化できる(まぁこれは普通)。


というわけで
親クラス
親クラス
名前
自作コントローラー


という構成でクラスを作って、大元クラスで親クラスを複数用意し、Addしまくって階層構造を作り、TreeViewにバインド。

しかし
名前しか出ん(´・ω・`)

バインド時にDataTemplateであれこれいじってもダメ。

無理なのか・・・?
いやまて、そのDataTemplateのXAMLコードを調べてみよう。
良く見ると並びがオブジェクトウィンドウのWindowの並びに似ている。
そうか、ということは・・・(-_☆)キラーン

結果
<HierarchicalDataTemplate>
<UserControler>
(ここにさっきまでTextBlockというコントローラーがあった)
</HierarchicalDataTemplate>

これだけでよい。
これだけで自作コントローラーを階層表示させることができる。
経験者なら分かるが、これは本来なら非常に面倒で果てしない作業だ。

しかし.NET3.0ならたったの3行(いや、その上にソース引用元とか書かなきゃいけないんだけど)。
しかもロジックコードではなく、XAMLのコードだけだ。

信じられん!
なんて簡単なんだ!!!
(ToT)
Posted at 2007/11/28 22:19:05 | コメント(0) | トラックバック(0) | プログラム | 日記
2007年11月21日 イイね!

【C#】リソースブラシを動的に更新【.NET3.0】

WPFにはブラシというクラスがある。
.NET2.0にもあるが、比べ物にならないくらい強烈なやつだ。
.NET2.0ではせいぜい2色グラデーション塗りで満足するレベルだったが、WPFでは複雑なグラデーションもいけるし画像もブラシとして扱える。
PicturePanelが無くなるわけだ。

で、
ブラシはリソース化できる。
リソースというのは、まぁHTMLで言えばjpgみたいなものか。
1個用意して、いろんなシーンで参照する。
ブラシをリソース化すればいろんなコントローラーで利用できるのだ。
そうすれば再利用もしやすいし、イメージの統一もたやすいわけよ。晴れ


今回、
背景を動的に更新する方法を調べた。
その背景というのはいろんなコントローラーで利用してまったく同時に更新される。
で、
更新パターンも非常に幾何学的。
ならば、TileBrush(タイルパターンで塗りつぶしてくれるブラシ)の数字をちょこちょこっといじるのが高速かつシンプルだろう。(-_☆)キラーン

というわけでアプローチを考えた。
①タイリングの数字をバインディング
②コードで数字を更新

この2つが候補だ。

①ならコードを書く必要はまったくない。
しかし無理だった(BLENDのバグじゃないか?)
そこで②を検証してみた。
更新方法はスライダーを利用。

スライダーの数値が変わった雷というメッセージを受け取って、その数値でリソースブラシをいじれば良いはず。
しかし・・・。

いや、リソースの取得は成功したんだ。
この関数内でFindResourcesを実行すれば簡単にできた。
このFindResourcesはどの階層にあるリソースでも拾ってくれるので便利なことこの上ない。

で、そのリソースをBrushにキャストして、タイリングのプロパティにスライダーの数値をぶち込めば、スライダーの動きに連動して全コントローラーの背景が動くはずなんだよ。
だが、ここで問題発生。
「読取専用」と言われて例外扱いされてしまうのだ。バッド(下向き矢印)
ならば
一旦コピーして、数字書き換えてそれをぶち込んでやる!ヽ(`Д´)ノ
例外は出なかった。
だが更新されない。バッド(下向き矢印)

なぜなんだぜ?(・ω・)

デバッグ情報ではちゃんと数字は更新されているようだが・・・。

こうなったら手も足も出ない。
助けを求めようにも、
こんな激レアなニーズ、ネットに文献があるはずもなく、社内のWPF使いはオレ一人。
あきらめて日報を書いた。そろそろ帰るか・・・。

否!
断じて否!!


.NET3.0の理念からしてできんはずがない!!
まだやる!!
むかっ(怒り)

というわけでインテリセンス出しまくって推理すること10数分。
SetValueというメソッドを発見。
そうか!
これだ!
これはDependencyPropertyに値をぶち込むヤツだ!

DependencyPropertyはなんだかよくわからんが、プロパティトリガーと深い関わりがある!!
これだあああああ!!!ぴかぴか(新しい)
素人プログラマーは論理より先に実行だぜ!(考えたってわからねー)

かくして
リソースブラシの動的更新は成功した。
そのコードは
リソースブラシをゲットして
数字を作って
SetValue


たったの3行だ。

これが.NET2.0なら
画像を保持するクラスを作ってそれを各コントローラーのサブクラスにし、タイミングを計って更新するのが合理的だろう(計算・描画と更新を分けて作るわけだ)。

初期化部分
画像クラスを実体化


更新情報受け取った
画像をクリア
DrawLineでちまちま描く(For文でタイリング数分まわす)


で、各コントローラーの描画ルーチンを呼んで

コントローラー描画部分(OnPaintオーバーライド)
自分の画像を、画像クラス情報で埋める。


とまぁ
描画計算が複雑でコントローラーが5個もあれば軽く100行は行く。そう、このブログのように。
色やフォントの保持、デリゲート設定などなど準備も大変だ。

それが.NET3.0なら
たったの3行!
\(^o^)/

もう.NET2.0には戻れねーーー!!(2ヶ月しかやってないけど)

管理もデバッグもカスタマイズも劇的に向上するぜ!?
なんでみんな使わないの!?
まじで感動するって!!
ああ、この感動を同僚ギャルに熱く語りたい・・・!!
Posted at 2007/11/22 01:03:58 | コメント(1) | トラックバック(0) | プログラム | 日記
2007年11月09日 イイね!

【C#】DependencyProperty【.NET3.0】

ブレイクスルー
いい響きだ。
日常でこれを実感できることはなかなか無い。
今日は久々にブレイクスルーがあったのでいつものようにメモするー。

自作プロパティにトリガーを設定する方法


コントローラーの種類が倍くらい増えた.NET3.0だが、やはり「欲しい」コントローラーは自作する必要がある。
当然、プロパティもニーズに合わせてぼこぼこ並べる。
.NET2.0ならなんの問題も無い。

だが、

C#ではアクセサがイベントドリブンのカギになっている。
値が変わったからイベント発生雷
この処理の最初の門はアクセサなのだ。
だから.NET2.0ではアクセサ内でイベントメッセージを発行させていた。
値が変わったから今すぐ画面の文字を書き換えて再描画しなさい雷
という具合だ。

これが.NET3.0のコーディングスタイルと矛盾するのだ。バッド(下向き矢印)

.NET2.0ならコーディングで再描画させるが、.NET3.0ではXAMLが定義する
つまりあらかじめ「どのプロパティが変わったらこの描画パターンを実行するか」を決めておくのだ(そのXAMLのエディタがBlend)。
だから、なんとかしてプロパティが変わったことを.NET3.0に知らせなければいけない。
それがプロパティトリガー雷だ。

このプロパティトリガー
標準のプロパティならドロップダウンで選べるのだが、自作モノは出てこない。
デリゲートでメッセージ発行させても出てこない。
本を紐解いても載ってない(参考書というものは大抵現場のニーズに応えてくれない)。

仕方ないので無理やりXAMLを書き換えて自作プロパティをトリガー化してみた。
エラーが出た。
そりゃそうかとガッカリしたが、よく読むと「DependencyPropertyではありません」と出ているではないか。
そうか。
DependencyPropertyにすればいいんだな!?(-_☆)キラーン

グーグルで調べまくってここにたどり着いた。
ここのサンプル通りに書いてうまく行った。
DependencyPropertyで悩んでいる諸君は参考にされたし。

public static readonly DependencyProperty IconColorProperty =
DependencyProperty.Register(
“IconColor”,
typeof(Brush),
typeof(PlayButton),
new FrameworkPropertyMetadata(Brushes.Black,
new PropertyChangedCallback(OnIconColorChanged
)));


ご覧のとおり、DependencyPropertyという型を宣言して、実際のプロパティの型は第2引数で指定している(ちなみに第1引数はホンモノのアクセサ)。
なんちゅー無茶苦茶なテクニックだ。型とか超無視じゃん(いや無視してないんだけど)。なんでもありじゃないか。
ゲイツこんなのよく作ったなぁ。
Posted at 2007/11/09 20:44:49 | コメント(0) | トラックバック(0) | プログラム | 日記
2007年11月06日 イイね!

寝ても覚めてもWPF

かつて
ウィンドウズアプリの開発はUIとの戦いだった。

生のCでWin32APIを直に叩くしか無かった頃、
そのコードは100行くらいになった。
窓を出すだけでだ
そこからマウスだメニューだと人力で組むわけだ。
プログラマーはある日気付く。

オレは窓作るためにプログラム書いてるんじゃねぇ!!
画面のサイズを変えたとき、中身のサイズが変わったとき、スクロールしたとき、
いちいちメッセージ拾って全部手で書いていたのである。



そしてMFCというライブラリがリリースされた。
VC++6を使えばウィザードが自動的に窓を組んでくれるのだ。
ある程度凝った作りもできるし、コントローラーやドキュメントのシリアライズも設けてくれる。
メモ帳程度なら30秒でできるわけだ。

これは感動した
世のプログラマーはマイクロソフトに涙を流して感謝し、喜んでお布施を納めたのである。
確かに、
何もかも自動でやってしまっては、いざというときカスタムしようにもどこに何があるか分からない。基礎をすっとばすこの仕組みは新人教育に支障をきたす。
そこに不安を覚えるプログラマーもいた。
しかし、ワタシは思った。
ゲイツマンセー!\(^o^)/

時は経ち、.NET frameworkの時代が来た。
データバインドという技術によってさらに窓操作が楽になった。
しかも型を柔軟に受け止めてくれるので(アリガタヤ)、コントローラーの入れ子が気軽にできるのだ。
つまり見た目がキレイなアプリを作りやすくなったのだ。
MFCの4倍は楽だ。
3倍じゃない。4倍だ。
ワタシは思った。
ゲイツマンセー!!\(^o^)/

.NET framework2.0をいじって2ヶ月。
世はいつのまにか.NET framework3.0に突入していた。
こいつにはWPFというライブラリが含まれている。
UI構築がさらに進化したのだ。
もはやUIのコードは存在しない
HTML風のマークアップ言語でUIを並べるのだ。
プログラマーはデータ処理ロジックに集中できる。
つまりコントローラーの位置に気を使う必要はないのである。
ついに
プログラマーは「窓のためのコーディング」から解放されたのである。
vistaのアプリがやたら垢抜けてるのはこのテクノロジーの恩恵
ゲイツマンセー!!

と言いたいところだが
コントローラーの動的追加をどうすればいいのかよく分からん。
,NET2.0の時と微妙にプロパティの名前が違ってるし。
コントローラーの種類も変わってる(さんざん世話になったPanelがねぇ)。

便利になりすぎたせいか、
ネット文献が超少ないヽ(`Д´)ノ


うかうかしてると取り残される。
勉強は死ぬまで終わらないだろう。
だがオレはアーバンなプログラマー。
アーバンなプログラマーはクールなUIをさらりと作らなきゃいけないんだぜ。
未だにC++で泥臭いダイアログアプリをひーこら作ってたらギャルにもてないぜ。

Posted at 2007/11/06 23:47:51 | コメント(2) | トラックバック(0) | プログラム | 日記
2007年09月13日 イイね!

【managed】ポストエフェクト【DirectX】

オレはシェーダーも書ける希少なデザイナーだ。
はっきり言って天才なんだが、一つ困っていることがある。

C#の参考文献が少なすぎる!
(正確にはC#+.NET)

その上ManagedDirectX、しかもシェーダーとなるとぐぐっても日本語サイト2,3件なんてこともザラだ。
本は重いしかさばるしコピペできないし
MSDNは下手な英語サイトより難解(しかもクソ重い)だ。

というわけで

生DirectX時代の文献からメソッドを類推する。
(-_☆)キラーン

まずはC++のメインからレンダー部分を精査する。

////////////////////
//イニシャライズ部分
////////////////////

D3DXCreateTextureFromFile(m_pd3dDevice, "weight.tga"
, &m_pTex);

D3DXCreateEffectFromFile(
m_pd3dDevice, "hlsl.fx", NULL, NULL,
D3DXSHADER_DEBUG , NULL, &m_pEffect, &pErr )

m_hTechnique = m_pEffect->GetTechniqueByName( "TShader" );
m_htMask = m_pEffect->GetParameterByName( NULL, "tMask" );
m_htSrc = m_pEffect->GetParameterByName( NULL, "tSrc" );

//////////////////////////////
//レンダリングルーチン
/////////////////////////////

//1パス目。レンダリングターゲット退避
//RenderState設定して
//マトリックス設定
//ジオメトリ、テクスチャ、マテリアル、ライト等置いて
//レンダリング
//2パス目。ターゲット戻して
//RenderState設定して
//さっきレンダリングしたサーフェスをテクスチャとして置いて
//板ポリDraw
//そしていよいよ

m_pEffect->SetTechnique( m_hTechnique );
m_pEffect->Begin( NULL, 0 );
m_pEffect->Pass( 0 );

//次にエフェクト用素材を作る。一般的な呼び方はWeightだ。
//同じくRenderState設定して(さっきと違って今度はブレンドモード)
//板ポリ用意して

m_pEffect->SetTexture(m_htMask, m_pTex);
m_pEffect->SetTexture(m_htSrc, m_pOriginalMap);


//板ポリDraw。これで終わり(のはず)

m_pEffect->End();

/////////////////////////////////////////////////


太字は特に密接に絡んでいるところ。
密接というかシェーダーの中の変数(?)そのものと言っていい。

わからんのが
2パス目のDrawのタイミングなんだよなぁ。
1パス目はDrawしてテクスチャに描き込んでいるが、2パス目はそのテクスチャと一緒にDrawしている。
一緒に渡しているからこそ画像変換できる、というのはまぁ至極当然なんだが、だったら1パス目を板ポリに貼ってDrawする必要なくね?
ノーマルレンダリングとノーマルをポストエフェクトかけたものをブレンドしてるのかな?
Posted at 2007/09/13 01:10:42 | コメント(1) | トラックバック(0) | プログラム | 日記

プロフィール

みんカラ新規会員登録

ユーザー内検索

<< 2025/9 >>

 123456
78910111213
14151617181920
21222324252627
282930    

リンク・クリップ

有楽町丸井 
カテゴリ:脱キモオタ
2007/09/15 15:55:54
 
Elastic 
カテゴリ:脱キモオタ
2007/02/13 00:55:22
 
スタイルコネクション 
カテゴリ:脱キモオタ
2007/02/13 00:33:58
 

愛車一覧

日産 180SX 日産 180SX
おっさんなのに180sx
© LY Corporation