WPFについての忘備録


___
# はじめに
C#,WPFについて個人的な忘備録をメモ...φ(..)
Version: .netframwork 4.0

# 目次
1.「MVVMパターン」について
2.「Binding」について
3.「Messenger」について
4.カスタムコントロール、ユーザーコントロールについて
5.コマンドについて
6.MediaElementについて
7.パフォーマンスについて
8.まとめ

# 1.「MVVMパターン」について
MVVMとは...Model,View,ViewModelで構成された設計パターンであり、それぞれ分離した役割を持つらしい。

|名前|役割|
|:---|:---|
|Model|ビジネスロジック|
|View|GUI|
|ViewModel|データ保持、ビジネスロジックへの伝達|
正直、Model,ViewModelの役割の分離はかなりめんどくさい。
設計の思想としては、それぞれの層は層内部で完結することを目指しています。
実際にコーディングした結果、ModelとModelView層が曖昧な結果となりました。
ですので、フルスクラッチ時は注意してください。

MVVMのメリットはそれぞれの層が分離しているので、分業が可能であることが挙げられますが、実際分業する場合は密なコミュニケーションが必要となります。

# 2.「Binding」について
WPFでは、View層の項目にViewModel層の変数を関連付けることで、View層の入力値をViewModelの変数に反映させる仕組みがあります。
これを「Binding」といいます。
「Binding」には多くのプロパティが用意されておりModelView層への反映タイミングを変更したりすることができます。

```

 <DataGrid x:Name="dgColorList"
           Height="2560"
           Margin="0,0,0,0"
           VerticalAlignment="Top"
           AutoGenerateColumns="False"
           CanUserAddRows="False"
           GridLinesVisibility="None"
           HeadersVisibility="None"
           IsReadOnly="True"
           ItemsSource="{Binding ColorList,
                                 UpdateSourceTrigger=PropertyChanged}"
           PreviewMouseDown="dgColorList_PreviewMouseDown"
           RowHeight="495"
           ScrollViewer.CanContentScroll="False"
           ScrollViewer.HorizontalScrollBarVisibility="Hidden"
           ScrollViewer.VerticalScrollBarVisibility="Hidden"
           SelectedItem="{Binding Path=CurrentRowItem,
                                  UpdateSourceTrigger=PropertyChanged}"
           SelectedValue="{Binding Path=ColorBarRGB,
                                   UpdateSourceTrigger=PropertyChanged}"
           SelectionMode="Single"
           VirtualizingPanel.IsVirtualizing="True"
           VirtualizingPanel.VirtualizationMode="Recycling">
     <DataGrid.Columns>
         <DataGridTemplateColumn>
             <DataGridTemplateColumn.CellTemplate>
                 <DataTemplate>
                     <ContentControl Content="{Binding UpdateSourceTrigger=PropertyChanged}" ContentTemplate="{StaticResource cellTemplate}" />
                 </DataTemplate>
             </DataGridTemplateColumn.CellTemplate>
         </DataGridTemplateColumn>
     </DataGrid.Columns>
 </DataGrid>

```

上記が一例です。
この場合、データグリッドにデータをバインドしています。
更に、*SelectedItem*,*SelectedValue*にもバインドを行っています。
*SelectedItem*をバインドすることによりユーザーが選択しているItemを逐一取得することが可能です。
これは、通常のイベントとは違いView層がViewModel層にプロパティが変わった事を通知します。

Bindingには、Converterという機能が用意されています。
これはViewModel層の変数型とView層の型が一致していない場合に変換して表示することが可能となります。
使用例としては、「DBには色のRBGの値が保存されており、画面には表示する際には、その色を再現する」といった場合に、RGBのINT型からBLUSHを生成するConverterを定義すれば実現が可能です。

# 3.「Messenger」について
WPFでは、「Binding」「Messenger」の使用がホットなようです。
ですが、「Messenger」は「Binding」にくらべてまだまだ使用頻度が少ないようです。
「Messenger」はViewModel層からViewへの通知を行う仕組みだそうです。
今回の案件では使用する場面がなかったので、必要な場面は少ないのかも知れません。

個人的な見解ですが、
コンバーターやメッセンジャーはそれぞれ専用クラスを定義しないといけないので、コードが煩雑になります。
よしんば構造が上手く行っても、デバック時に追いにくいことになりそうなので、本当に必要な場合のみ使用する方が良いと思います。


# 4.カスタムコントロール、ユーザーコントロールについて
WPFにはカスタムコントロール、ユーザーコントロールがそれぞれ存在しています。

|名前|用途|用法|
|:---|:---|:---|
|カスタムコントロール|独自コントロール|Customタグで生成する|
|ユーザーコントロール|コントロールの集まり|Viewsタグで生成する|
似たような感じですが、カスタムコントロールはWindowsFormでいうユーザーコントロールです。
ユーザーコントロールは、コントロールを纏めたパネルのようなものを想像いただければよいかと思います。

WPFは、標準のコントロールの見た目がイケておりません。
素人目から見てもダメダメです。そこで、見た目を変えよう！！というそこの人！！
WPFのコントロールの見た目だけであればそこまで苦労せずに済みますが、中身や挙動を変える際にはMSDNからカスタマイズのテンプレートをコピーしてきてから変更する方法を強くおすすめします！！！
というのも、一見簡単そうなコントロールでもいろいろなコントロールが使用されており、思い通りにカスタマイズできないことが大半だからです。
CSSかける人なた余裕なのかもしれませんが...

# 5.コマンドについて
WPFでは、イベントとは別にコマンドを定義することが可能です。
C#はイベントドリブンなプログラミング言語です、なのでWPFでもそれは変わりません。
イベントが発生するとコードビハインドに定義したイベントが発生するわけですが、WPFではできるだけコードビハインドを薄くしなければ各層の独立性が失われてしまいます。
コードビハインドを薄くするため(?)にWPFにはコマンドという機能があります。
ですが、癖があるので以下にメリットデメリットを列挙します。
* メリット
 1.コードビハインドを介さずにViewModelのメソッドを呼び出せる
 2.コマンドパラメーターを設定できるので、ViewModelのメソッド内で柔軟に分岐が可能
 3.C#のコードではなくXAMLのコードで書くのでバグが少なくなる
 4.NoCommandを設定することで、画面の入力状態などで可変にコード実行可否を定義可能
* デメリット
 1.WPFを知らない人又は、コマンドを知らない人にとっては記述が結びづきにくい
 2.Buttonコントロール等、一部のコントロールにしかコマンド機能が存在していない
 3.コマンドは基本的に実行の場合にしか呼ばれない(holdやchangedイベントは存在しない)
 4.コマンドを別途定義する必要になる

コマンドとイベントを組み合わせることにより、通知経路が変わるのでよりソースを追いづらくなる可能性があるので、ご一考ください。
また、コマンドの定義にも癖があるので、最初は受け入れにくいと思われます。
個人的には、全てイベントでするのがベターな気がします。

# 6.MediaElementについて
WPFにはmediaElementとmediaPlayerという動画再生用のコントロールが存在します。
ですが、動画を流し続けるとメモリリークが発生するというバグがあります。
※ 4.0時点ですので、後で修正されているかも知れません。
基本的に回避できませんので、動画を流し続ける必要がある場合は、以下の方法を検討ください。
* 別のMediaPlayerを使用する
* アプリケーションの構成を変更し、アプリケーションの再起動を行う。

# 7.パフォーマンスについて
WPFはGUPを酷使します。より滑らかにサクサク動かしたいのであればGPUのスペックに注意してください。
GPUが貧弱な業務用PCとか、正直きついです。パフォーマンスを求めるならWindowsフォームで開発してください。
それでも、どうにか軽くしたいを言う方には、*isHitVisible*プロパティを調整してください。
WPFのコントロールはコントロールの集合体です。本当は無視してもいいイベントでも発火してしまいます。
なので、そのイベントを発火させないようにするのが、*isHitVisible*プロパティです。
これを設定すると触れないオブジェクトとして画面表示されます。後はVisualTreeと戦ってください。
他にも改善する方法はあると思いますが、一番有効的な方法化と思います。

# 8.まとめ
WPFは自由度高い分作る際にも色々なテクニックが必要
パフォーマンスには気を付けて
回避できないバグは知恵と勇気で乗り越えて
Blendばっかりに頼るとXAMLがよめなくなる！！
コード構造が重要！！
WPFには機能があるが、全てが使える訳ではない（取捨選択が大事）
___