[[Open棟梁Project>http://opentouryo.osscons.jp/]] - [[マイクロソフト系技術情報 Wiki>http://techinfoofmicrosofttech.osscons.jp/]] -[[戻る>WPF]] * 目次 [#n83520fb] #contents *概要 [#q1a484b6] *WPFの機能 [#i739b5f5] **サポートする機能 [#t4e8816f] ***グラフィック [#h896dbc6] -2D/3Dグラフィック・レンダラー~ 従来は、2D(図形、ブラシ、ペン)はGDI、3D (光源、カメラ位置情報)はDirect3D、ビデオはDirectShowなど、異なるAPI群を組み合わせていたが、WPFのUIフレームワークでは、これらを統一して扱えるようになっている。また、透過性をサポートしている。 -ベクタ グラフィック~ 従来のラスタ グラフィックから、画素密度非依存のベクタ グラフィックに変更され、画素密度の変更や、拡大・縮小をしても、画質が維持される。 --WPF グラフィックス レンダリングの概要~ http://msdn.microsoft.com/ja-jp/library/ms748373.aspx -GPUレンダリング~ CPUによりビットマップ イメージのレンダリングを行っていた[[GDI, GDI+>GDI]]から、Direct3D経由でGPUを使用するレンダリングに変更されている。このため、CPU描画の他の技術より高速で、同時にCPUへの負担を最小限に抑えることができる。 ***メディア [#ae89eda3] -ドキュメント --WPFドキュメント(XPSドキュメントやフロー ドキュメント)を表示できる 。 --ドキュメント表示のためのFixedDocument、FlowDocumentコントロールが標準で提供されている。 -イメージ --JPEGやGIFなど多様な形式のイメージを表示できる 。 --静止画を表示するためのImageコントロールが標準で提供されている。 -ビデオ --WMV、AVI、MPEGなど多様な形式のメディアを表示できる 。 --動画や音声を再生するためのMediaElementコントロールが標準で提供されている。 ***コントロール [#he1818af] -コントロール種類~ --Windowsの標準的なUIを実装するために必須である、基本的な組み込みコントロールが提供される。 --なお、HTMLと同様に、これらのコントロール類をXAMLで実装するため、コントロール単位にXAMLタグが用意されている。 -データ バインディング~ UIコントロールと、CLRオブジェクトの間をマッピングする。 -スタイル・テンプレート~ UIコントロールの「外観」や、イベント ハンドラ・イベント トリガなども含めた、UIコントロールの標準化・カスタマイズを行う。 ***レイアウト [#t2c0cd22] パネルと呼ばれるレイアウト用コントロールを使用して、Windowsフォームのような座標レイアウト、HTMLのようなフロー レイアウト(ブロック化、格子分割)にも対応する。 ***アニメーション [#r34f5a3d] イベント トリガ、トリガ アクション、ストーリ ボードを定義することで、UIコントロールなどの表示項目にタイムライン ベースのアニメーションの効果を付加できる。 ***デプロイ [#s2a81ed7] ClickOnce、[[XBAP]]などのデプロイが可能。 ***相互運用性 [#x4bb8f7f] P/InvokeやRCW呼出しなどWin32連携技術を使用した相互運用が可能である。また、WindowsFormsHost、Hwndhost を使用することで、WindowsフォームやActiveXのUIコントロールを使用することも可能である(パフォーマンス的には不利)。 例えば、下記は、System.Windows.Forms名前空間のDataGridコントロールをホストするWPFの例である。 <Window x:Class="WpfApplication1.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms" Title="HostingWfInWpf" Height="150" Width="300" Loaded="Window_Loaded"> <Canvas> <WindowsFormsHost Name="windowsFormsHost1" Height="100" Width="275"> <wf:DataGrid x:Name="dataGrid1"/> </WindowsFormsHost> </Canvas> </Window> -参考 --MSDN > Windows Presentation Foundation > 移行と相互運用性 ---Windows フォームと WPF の相互運用性入力アーキテクチャ~ http://msdn.microsoft.com/ja-jp/library/ms742474.aspx ---WindowsFormsHost要素のレイアウトに関する考慮事項~ http://msdn.microsoft.com/ja-jp/library/ms744952.aspx ---チュートリアル:WPFでのWindowsフォーム複合コントロールのホスト~ http://msdn.microsoft.com/ja-jp/library/ms750944.aspx ---チュートリアル:WPFでの、XAMLを使用したWindowsフォーム コントロールのホスト~ http://msdn.microsoft.com/ja-jp/library/ms742875.aspx ---チュートリアル:WPFでのActiveXコントロールのホスト~ http://msdn.microsoft.com/ja-jp/library/ms742735.aspx --@IT > Insider.NET > .NET TIPS ---WPF/XAMLでWindowsフォームを利用するには?[3.0,3.5,VS2008,C#、VB]~ http://www.atmarkit.co.jp/fdotnet/dotnettips/802winformonwpf/winformonwpf.html ---WindowsFormでWPFコントロールを利用するには?[3.0,3.5,VS2008,C#、VB]~ http://www.atmarkit.co.jp/fdotnet/dotnettips/800wpfonwinform/wpfonwinform.html **機能の制限事項 [#u458510e] 主に3Dグラフィックの高度な機能に関する制限であるので、リッチでインタラクティブな業務アプリケーションの開発に、大きな支障は無いと言える。 |項番|区分|説明|h |1|パフォーマンス|Direct3Dと比べるとオーバーヘッドがあり、GPU負荷が高くなる。また、WPFはDirect3D 9対応であり、Direct3D 10対応のグラフィックボードであってもパフォーマンスは向上しない。| |2|シェーダ|WPFは内部的にシェーダを使用しているが、開発者がWPFからシェーダを使用することはできない。| |3|スキニング |WPFではスキニングができないので、滑らかな関節を持つアニメーションはできない(剛体アニメーションのみサポート)。| |4|環境マッピング|WPFでは環境マッピングが使用できないので、物体に周囲の景色が反射しているような効果は表現できない。| |5|影|WPFではステンシル バッファ(3Dグラフィックにおいて、物体の重ね合わせなど、描画しなくても良い領域を効率よく判定するためのバッファ領域)や、深度バッファを使用できないためリアルな影を生成できない。| |6|テクスチャ・フィルタリング|ポリゴンのテクスチャを構成するピクセルにテクセル(3Dグラフィックにおいて、テクスチャを構成する一つ一つのピクセル)が一対一に対応することはほとんどなく、&br;ポリゴンにテクスチャをマッピングする際には、テクスチャを拡大/縮小(変形)するフィルタが必要となるが、WPFから、このフィルタを指定することはできない。| ***シェーダ [#a950b4f0] 3Dグラフィックにおいて、グラフィック リソースに対して光源計算、陰影処理とレンダリング(ピクセル化)を実行するために使用するソフトウェア命令の組み合わせ。シェーダには、3Dグラフィックを、2Dグラフィックのように表示するトゥーン シェーダや、毛筆で描かれたような水彩画風の特殊な絵のタッチで表示する筆シェーダなどがある。 ***スキニング [#ed4a07a2] 3Dグラフィックにおいて、人間の関節のような滑らかな屈曲を表現するための手法。 ***環境マッピング [#s6a808fc] 3Dグラフィックにおいて、レイトレーシングを使わずに反射率の高い表面をシミュレートするテクニック。オブジェクトを囲むシーンの画像を含む特殊なテクスチャを、オブジェクト自体に適用する。結果、反射面の特徴を上手く模倣し、膨大な計算を必要とするレイトレーシングを使わずに、十分実用的なものになる。 **注意事項 [#h510ff35] ***標準UIコンポーネント [#q96953fc] 初期は不足があり、サードパーティ製品に依存していたが、最近は拡充された。 ***帳票ビューア [#d5c323d7] 初期はサードパーティ製品に不足があったが、最近は拡充された。 ***座標レイアウト [#a944f035] Windowsフォームの開発と同様に、VSデザイナからコントロールをD&Dして座標レイアウトでコントロール位置を指定する方式の開発を望む場合は、パネル要素に、Canvasコントロール(後述)を使用する。 *WPFアーキテクチャ [#ub42debb] -MSDN > WPFの基礎 > WPFアーキテクチャ~ http://msdn.microsoft.com/ja-jp/library/ms750441.aspx **クラス階層 [#b319c3db] System.Object -System.Threading.DispatcherObject -System.Windows.DependencyObject -System.Windows.Media.Visual -System.Windows.UIElement -System.Windows.FrameworkElement -System.Windows.Controls.Control -System.Windows.Controls.ContentControl -System.Windows.Controls.ItemsControl ***System.Object [#d4af4c32] http://msdn.microsoft.com/ja-jp/library/system.object.aspx WPFのプログラミング モデルを提供するフレームワークは、CLR上のマネージ コンポーネント(PresentationFramework.dll、PresentationCore.dll)として公開される。System.Objectは、マネージ コンポーネントが提供する全てのマネージ クラスの基本クラスであり、型階層のルートである。 マネージ コンポーネントには、開発の生産性と信頼性を高める多数の機能(メモリ管理、エラー処理、共通型システムなど)が用意されているが、性能など犠牲となるものもある。これに対し、アンマネージ コンポーネント(milcore.dll)はDirectXとの緊密な統合の実現(ハードウェア レンダリングおよびソフトウェア レンダリングの効率性を考え、WPF での表示はすべて DirectX エンジンによって実行されるようになっている。)、メモリ・実行の詳細な制御の要件による。 ***System.Threading.DispatcherObject [#y115b7e3] http://msdn.microsoft.com/ja-jp/library/system.windows.threading.dispatcherobject.aspx DispatcherObjectは、派生したCLRオブジェクトに、[[STA]]オブジェクトとしての動作を実装する基本抽象クラスである。 通常、WPFアプリケーションは、 -レンダリング スレッド:レンダリングを処理するスレッド -UIスレッド:アプリケーションの主スレッド(イベント処理、UI処理) の2つのスレッドを使用して実行される。 「レンダリング スレッド」は、「UIスレッド」がユーザ入力を受け取り、イベント処理・UI処理をしている間に、バック グラウンドで実行される。このため、ほとんどのWPFアプリケーションは、単一の「UIスレッド」で済むが、状況によっては、応答性を高める目的でバック グラウンド スレッドを使用する場合もある。WPFでは、バック グラウンド処理の実装を支援するDispatcherObjectを使用できる。 -MSDN > WPFの基礎 > スレッド モデル~ http://msdn.microsoft.com/ja-jp/library/ms741870.aspx DispatcherObject.Invoke、BeginInvokeメソッドを使用することにより、バック グラウンド処理からの「UI変更処理」(= UI要素の操作処理)が、容易に実装可能となる。 -MSDNマガジン > 発行物 > WPFのスレッド:Dispatcherを使用して応答性の高いアプリケーションを構築する~ http://msdn.microsoft.com/ja-jp/magazine/cc163328.aspx -MSDN > .NET Frameworkクラス ライブラリ --System.Windows.Threading.Dispatcher.Invokeメソッド~ http://msdn.microsoft.com/ja-jp/library/system.windows.threading.dispatcher.invoke.aspx >このメソッドに指定されたデリゲートは、同期実行されるため、バック グラウンド スレッドが実行結果を表示する「UI変更処理」に利用することが多い。 --System.Windows.Threading.Dispatcher.BeginInvokeメソッド~ http://msdn.microsoft.com/ja-jp/library/system.windows.threading.dispatcher.begininvoke.aspx --System.Windows.Threading.DispatcherPriority列挙体~ http://msdn.microsoft.com/ja-jp/library/system.windows.threading.dispatcherpriority.aspx これらのメソッドは、内部的には -([[STA]]と同様にスレッド間通信の手段である)[[Windowsメッセージキュー>ウィンドウ メッセージ#zdf9603f]]にUI変更処理をエンキューする。 -エンキューされた「UI変更処理」は、「UIスレッド」がアイドル状態の際にデキューされて、「UIスレッド」により処理される。 これにより、 -「UI変更処理」は、必ず、特定の「UIスレッド」により処理されるようになる。 -マルチ スレッド処理においてスレッド セーフではないUIコントロールの変更処理が問題とならなくなる。 ***System.Windows.DependencyObject [#ie0208ee] http://msdn.microsoft.com/ja-jp/library/system.windows.dependencyobject.aspx DependencyObjectは、派生したCLRオブジェクトに「[[WPFプロパティ システム>#u00b87e5]]」を実装する。 WPFのアーキテクチャの理念は、「メソッドやイベント(コードビハインド)よりも、なるべくXAMLのマークアップによる宣言的プロパティを使用する」ことである。これを実現する「[[WPFプロパティ システム>#u00b87e5]]」を実装するDependencyObjectにより、開発者は多数の宣言的プロパティを使用し、コントロールに開発者の意図を設定できる。このためWPFの開発元は、このXAMLのマークアップによる宣言的プロパティによる制御の範囲を拡大するために、「[[WPFプロパティ システム>#u00b87e5]]」の「依存関係プロパティ」が必要であると判断した。「依存関係プロパティ」は、プロパティの依存関係を把握し、双方向の接続と変更通知を実現する。具体的には、ソースとなるオブジェクトのプロパティの変更が通知された場合(必須ではないが、INotifyPropertyChangedインターフェイスを使用すると、オブジェクトによる変更通知の発行が可能になる。)、ターゲットとなるオブジェクトのプロパティ値を自動的に検証、計算するなど、高度なオブジェクト プロパティ間の接続を実現する。 -MSDN > .NET Frameworkクラス ライブラリ~ System.ComponentModel.INotifyPropertyChangedインターフェイス~ http://msdn.microsoft.com/ja-jp/library/system.componentmodel.inotifypropertychanged.aspx 「依存関係プロパティ」の入力には、次のものがある。 -動的な「リソース」 --「スタイル」 --「テンプレート」 --「アニメーション」 -「データ バインディング」 --「ビュー・モデル オブジェクト」 -「添付プロパティ」~ 親子要素のリレーションの値(子要素 → 親要素)を設定する。 -「プロパティ値の継承」~ 親子要素のリレーションの値(親要素 → 子要素)を設定する。 ***System.Windows.Media.Visual [#s4219d62] http://msdn.microsoft.com/ja-jp/library/system.windows.media.visual.aspx Visualは、WPF の中心的な機能である描画をサポートする基本抽象クラスである。 Visualは、マネージ コンポーネントとアンマネージ コンポーネントの2つのサブシステムの接続ポイントであり、Visualで定義されているマネージ データ(描画情報、描画方法など)から、「ビジュアル ツリー」(後述)と呼ばれるツリー構造のアンマネージ データを構成する。これを「レンダリング スレッド」がツリー構造の上から下にスキャンすることによって描画内容をレンダリングする。 -WPF グラフィックス レンダリングの概要~ http://msdn.microsoft.com/ja-jp/library/ms748373.aspx -出力表示 : 描画内容をレンダリングする。 --クリッピング : CGで、画像の一部を切り抜く。 --変換 : 変換(回転、拡大縮小、傾斜、平行移動)を実行する。 --境界の計算 : ビジュアルの外接する四角形を決定する。 --ヒット テスト : 境界に含まれているかどうかを判定する。 -プロパティの例 --VisualOpacity : 不透明度~ http://msdn.microsoft.com/ja-jp/library/system.windows.media.visual.visualopacity.aspx --VisualOpacityMask : 不透明マスク~ http://msdn.microsoft.com/ja-jp/library/system.windows.media.visual.visualopacitymask.aspx --VisualClip : クリッピング(クリップ領域の決定)~ http://msdn.microsoft.com/ja-jp/library/system.windows.media.visual.visualclip.aspx --VisualTransform : 変換(ビジュアルの変換値)~ http://msdn.microsoft.com/ja-jp/library/system.windows.media.visual.visualtransform.aspx --VisualEdgemode : 端の描画方法~ http://msdn.microsoft.com/ja-jp/library/system.windows.media.visual.visualedgemode.aspx -Visualオブジェクトの階層構造 ┬Visual ├UIElement │└FrameworkElement ├ContainerVisual │├DrawingVisual │├HostVisual └Viewport3DVisual --System.Windows.Media.ContainerVisualクラス~ http://msdn.microsoft.com/ja-jp/library/system.windows.media.containervisual.aspx~ Visualオブジェクトのコレクションのコンテナとして使用される。 --System.Windows.Media.DrawingVisualクラス~ http://msdn.microsoft.com/ja-jp/library/system.windows.media.drawingvisual.aspx~ 図形(ベクタ グラフィックス)、イメージ、モニター(ビデオ)、グリフ(テキスト)の描画に使用する描画クラス。レイアウトやイベントの処理を実現しないため軽量で、背景やクリップ アートの描画に適す。また、ContainerVisualクラスから派生するため、Visualオブジェクトのコレクションを格納できる。 --System.Windows.Media.Media3D.Viewport3DVisualクラス~ http://msdn.microsoft.com/ja-jp/library/system.windows.media.media3d.viewport3dvisual.aspx~ 2DのVisualオブジェクトとVisual3Dオブジェクト間のブリッジを提供する。Viewport3DVisualでは、Cameraプロパティ(シーンを表示)とViewportプロパティ(投影をサーフェイス上にマップ)を定義する必要がある 。 -Visualオブジェクトの描画コンテンツ~ Visualオブジェクトは、描画コンテンツを格納した下記の4種類のレンダリング データを命令リストとして格納する。また、命令リストを表すオブジェクトとして、DrawingGroupオブジェクト、Drawingオブジェクトがある 。なお、Drawingクラスは基本抽象クラスであり、描画コンテンツの種類(ベクタ グラフィックス、イメージ、モニター、グリフ)に合わせて、様々な派生クラス(GeometryDrawing 、ImageDrawing 、VideoDrawing 、GlyphRunDrawing )がある。 --System.Windows.Media.Drawingクラス~ http://msdn.microsoft.com/ja-jp/library/system.windows.media.drawing.aspx --System.Windows.Media.DrawingGroupクラス~ http://msdn.microsoft.com/ja-jp/library/system.windows.media.drawinggroup.aspx --System.Windows.Media.GeometryDrawingクラス~ http://msdn.microsoft.com/ja-jp/library/system.windows.media.geometrydrawing.aspx --System.Windows.Media.ImageDrawingクラス~ http://msdn.microsoft.com/ja-jp/library/system.windows.media.imagedrawing.aspx --System.Windows.Media.VideoDrawingクラス~ http://msdn.microsoft.com/ja-jp/library/system.windows.media.videodrawing.aspx --System.Windows.Media.GlyphRunDrawingクラス~ http://msdn.microsoft.com/ja-jp/library/system.windows.media.glyphrundrawing.aspx -MSDN > Windows Presentation Foundation > グラフィックスとマルチメディア --Drawingオブジェクトの概要~ http://msdn.microsoft.com/ja-jp/library/ms751619.aspx --方法:GeometryDrawingを作成する~ http://msdn.microsoft.com/ja-jp/library/ms742533.aspx --方法:ImageDrawingを使用してイメージを描画する~ http://msdn.microsoft.com/ja-jp/library/ms753315.aspx --方法:VideoDrawingを使用してメディアを再生する~ http://msdn.microsoft.com/ja-jp/library/aa969812.aspx -Visualオブジェクトの命令リスト |項番|命令リスト|説明|h |1|ベクタ グラフィックス&br;(GeometryDrawing)|Geometry、Pen、Brushなどのベクタ グラフィックス データ| |2|イメージ&br;(ImageDrawing)|デジタル メディア ファイル内の各種イメージ| |3|モニター&br;(VideoDrawing)|デジタル メディア ファイル内の各種ビデオ| |4|グリフ&br;(GlyphRunDrawing)|テキストとフォントで表わされるグリフ&br;(特定のフォントにおける文字の物理表現)| --System.Windows.Media.Geometryクラス~ http://msdn.microsoft.com/ja-jp/library/system.windows.media.geometry.aspx --System.Windows.Media.Penクラス~ http://msdn.microsoft.com/ja-jp/library/system.windows.media.pen.aspx --System.Windows.Media.Brushクラス~ http://msdn.microsoft.com/ja-jp/library/system.windows.media.brush.aspx -レンダリング データのレンダリング~ Visualオブジェクトの描画コンテンツであるベクタ グラフィックスのレンダリング データは、DrawingVisual・DrawingImage オブジェクトのDrawingプロパティに設定されたDrawingGroupオブジェクト内の1つ以上のDrawingオブジェクト、もしくはDrawingオブジェクトのPen・Brushプロパティとして表される。なお、DrawingVisual・DrawingGroupオブジェクトに、DrawingGroup、Drawingオブジェクトを設定するには、DrawingContextオブジェクトを取得して行う。DrawingImageオブジェクトにDrawingGroup、Drawingオブジェクトを設定するには、コンストラクタを使用する。DrawingVisual・DrawingImageオブジェクトが「レンダリング スレッド」によりレンダリングされるとき、DrawingGroupオブジェクトは、自身に設定されているプロパティを次の順に適用する。 ++Children ++OpacityMask ++Opacity ++BitmapEffect ++ClipGeometry ++GuidelineSet ++Transform ***System.Windows.UIElement [#de06b271] http://msdn.microsoft.com/ja-jp/library/system.windows.uielement.aspx UIElementは、WPFコア レベル実装の基本クラス -目的~ UIElementは、WPFコア レベル実装の基本クラスで、下記を目的とする。 --派生クラスで、オーバーライドする仮想メソッドを公開する。 --派生クラスで、仮想メソッドをオーバーライドすることによって、中心的なサブシステムを定義する。 ---「レイアウト」 ---「ルーティング イベント」 --自要素と子要素の「レイアウト」を操作する。 --キーボード、マウス、およびスタイラスなどによる入力操作に~ 対する「ルーティング イベント」と、関連するプロパティが含まれる。 -機能 --子要素の「レイアウト」(サイズ指定・配置) --ユーザ入力への応答、「ルーティング イベント」 --「アニメーション」システムを部分的にサポート -プロパティの例 --IsEnabled : UI要素の有効・無効~ http://msdn.microsoft.com/ja-jp/library/system.windows.uielement.isenabled.aspx --Visibility : UI要素の可視性~ http://msdn.microsoft.com/ja-jp/library/system.windows.uielement.visibility.aspx --AllowDrop : D&Dの有効・無効~ http://msdn.microsoft.com/ja-jp/library/system.windows.uielement.allowdrop.aspx --Focusable : フォーカスの有効・無効~ http://msdn.microsoft.com/ja-jp/library/system.windows.uielement_properties.aspx --RenderTransform : 変換(アニメーションや一時効果の追加)~ http://msdn.microsoft.com/ja-jp/library/system.windows.uielement.rendertransform.aspx ***System.Windows.FrameworkElement [#ed372988] http://msdn.microsoft.com/ja-jp/library/system.windows.frameworkelement.aspx UIElementに、「レイアウト」、「スタイル」を中心とした機能を追加する基本クラス。 -概要~ FrameworkElementは、UIElementの仮想メンバへ、以下を導入することを目的とする。 --ポリシー・カスタマイズの導入 ---「レイアウト」 ---動的「リソース」 ---「スタイル」 : 「テンプレート」は、FrameworkElementではなく、コントロール クラスによって導入される。 ---「アニメーション」 : アニメーションは、 UIElementで定義されているが、FrameworkElementでは、FrameworkElement.BeginStoryboardメソッドと、その関連メンバを実装することによって拡張できる。 ---「データ バインディング」 --新しいサブシステムの導入 -機能 --追加の「レイアウト」特性の定義 --動的「リソース」 ---「スタイル」のサポート ---「アニメーション」のサポートの強化 --「データ バインディング」 -プロパティの例 --Style : 使用されるスタイル~ http://msdn.microsoft.com/ja-jp/library/system.windows.frameworkelement.style.aspx --UseLayoutRounding : サイズと位置の丸め要・否~ http://msdn.microsoft.com/ja-jp/library/system.windows.frameworkelement.uselayoutrounding.aspx --LayoutTransform : 変換(回転、拡大縮小、傾斜、平行移動)~ http://msdn.microsoft.com/ja-jp/library/system.windows.frameworkelement.uselayoutrounding.aspx ***System.Windows.Controls.Control [#p2c5df5e] http://msdn.microsoft.com/ja-jp/library/system.windows.controls.control.aspx 「テンプレート」を使用して外観を定義する UI 要素の基本クラス Controlの最も重要な機能は、「テンプレート」である。この「テンプレート」により、コントロールの「外観」を宣言型マークアップでカスタマイズ可能になる(「テンプレート」を複数の子要素から構成する)。また、「イベント ハンドラ」や「イベント トリガ」などもこの「テンプレート」により定義可能で、「テンプレート」を「スタイル」化することで、任意の型のコントロールに、これらの「テンプレート」の定義の適用を強制できる。 ***System.Windows.Controls.ContentControl [#e85cfa8d] http://msdn.microsoft.com/ja-jp/library/system.windows.controls.contentcontrol.aspx ContentControl は、Contentプロパティを持つコントロールであるContentControlも、Contentプロパティの表示に特化した「テンプレート」を持つ。Contentプロパティには、文字列に限らず、様々な子要素を1つだけ設定可能である。代表的なContentControl型の(ContentControlクラスから派生した)コントロールには、Button、CheckBox、RadioButtonなどがある。なお、プロパティへ子要素を設定するXAML構文を、 -「プロパティ属性構文」 -「プロパティ要素構文」 と呼び、この中で、特にContentプロパティに子要素を設定するXAML構文を「コンテンツ構文」と呼ぶ。 ***System.Windows.Controls.ItemsControl [#j79a4288] ItemsControlは、1つのコンテンツを設定するContentControlに対し、複数のコンテンツを設定できるItemsコレクション プロパティを持つコントロールである。ItemsControlも、Itemsコレクション プロパティの表示に特化した「テンプレート」を持つ。Itemsコレクション プロパティには、様々な子要素を複数設定可能である。代表的なItemsControl型の(ItemsControlクラスから派生した)コントロールには、ComboBox、ListBox、TabControl、TreeViewなどがある。なお、同様にItemsコレクション プロパティに子要素を設定するXAML構文を「コンテンツ構文」と呼ぶ。 **要素ツリー [#p05c4c4f] WPFは、ビジュアル要素や、CLRオブジェクトによる「要素ツリー」を構築して、それを処理することでディスプレイへの表示を行う。 「要素ツリー」は、XAMLやプログラムにより、構築される。 -MSDN > Windows Presentation Foundation > 方法 : 要素を動的に追加する~ http://msdn.microsoft.com/ja-jp/library/ms752374.aspx 例えばXAMLは、次の「プロパティ要素構文」の暗黙的、または明示的な記述で、ツリー構造のCLRオブジェクトをインスタンス化する。 -DockPanel.Children(Panel.Children)プロパティ -ListBox.Items(ItemsControl.Items)プロパティ <DockPanel> <!--implicit: <DockPanel.Children>--> → プロパティ要素構文(省略可能) <ListBox DockPanel.Dock="Top"> <!--implicit: <ListBox.Items>--> → プロパティ要素構文(省略可能) <ListBoxItem> <TextBlock>Dog</TextBlock> </ListBoxItem> <ListBoxItem> <TextBlock>Cat</TextBlock> </ListBoxItem> <ListBoxItem> <TextBlock>Fish</TextBlock> </ListBoxItem> <!--implicit: </ListBox.Items>--> → プロパティ要素構文(省略可能) </ListBox> <Button Height="20" Width="100" DockPanel.Dock="Top">Buy a Pet</Button> <!--implicit: </DockPanel.Children>--> → プロパティ要素構文(省略可能) </DockPanel> ただし、「要素ツリー」は、実体そのものではない「メタファ」であるため、XML DOM のようなXMLツリー操作用のAPIを使用して直接操作することはない。これは、WPFのUIサブシステムのアーキテクチャ、UIフレームワークの構造を理解する上で役立つ。「要素ツリー」には、「論理ツリー」・「ビジュアル ツリー」の2つの解釈方法がある。 -MSDN > WPFの基礎 > WPFのツリー~ http://msdn.microsoft.com/ja-jp/library/ms753391.aspx ***論理ツリー [#ofdb8805] 「論理ツリー」は、CLRオブジェクトの要素のツリーを表し、「プロパティ継承」や、「ルーティング イベント」を理解する上で役立つ。 以下のXAMLとコードは、同じ「論理ツリー」(CLRオブジェクトの要素のツリー)を生成するため、同じUIを表示する。 -XAML <DockPanel> <ListBox Width="100"> <ListBoxItem>Dog</ListBoxItem> <ListBoxItem>Cat</ListBoxItem> <ListBoxItem>Fish</ListBoxItem> </ListBox> <Button Click="OnClick">OK</Button> </DockPanel> -コード ビハインド DockPanel dp = new DockPanel(); ListBox lbx = new ListBox(); lbx.Width = 100; ListBoxItem lbxItem = null; lbxItem = new ListBoxItem(); lbxItem.Content = "Dog"; lbx.Items.Add(lbxItem); lbxItem = new ListBoxItem(); lbxItem.Content = "Cat"; lbx.Items.Add(lbxItem); lbxItem = new ListBoxItem(); lbxItem.Content = "Fish"; lbx.Items.Add(lbxItem); dp.Children.Add(lbx); Button btn = new Button(); btn.Content = "OK"; btn.Click += new RoutedEventHandler(this.OnClick); dp.Children.Add(btn); this.AddChild(dp); ***ビジュアル ツリー [#o813f26f] 「ビジュアル ツリー」は、「論理ツリー」と異なり、ビジュアル要素のツリーを表し、コントロールの「テンプレート」が展開される。このため、アプリケーションのUIで使用する、全てのVisualオブジェクト(描画内容)が含まれる。 -レンダリング順序~ 「ビジュアル ツリー」階層の最上位の要素(ルート ビジュアル)から、左から右に幅優先で走査・レンダリングされる。 -ルート ビジュアル~ ルート ビジュアルは、「ビジュアル ツリー」階層の最上位の要素で、ほとんどのアプリケーションでは、ルート ビジュアルは以下のいずれかになる。 --Window : 「Window画面」 --NavigationWindow : 「ナビゲーション フレームワーク」 --Win32アプリケーションにホストされる場合、Win32ウィンドウにホストされる最上位のビジュアル要素がルート ビジュアルになる。 >MSDN > Windows Presentation Foundation > チュートリアル:~ Win32アプリケーションでのビジュアル オブジェクトのホスト~ http://msdn.microsoft.com/ja-jp/library/ms754039.aspx ***論理ツリーと、ビジュアル ツリーの確認方法 [#k6ab5976] 実際に、「要素ツリー」の内容を確認したい場合は、以下のヘルパ クラスのGetChildrenメソッドを再帰的に使用して、各ツリーを出力すると良い。 -LogicalTreeHelper:「論理ツリー」の子要素を照会~ http://msdn.microsoft.com/ja-jp/library/system.windows.logicaltreehelper.aspx -VisualTreeHelper:「ビジュアル ツリー」の子要素を照会~ http://msdn.microsoft.com/ja-jp/library/system.windows.media.visualtreehelper.aspx 上記のヘルパ クラスの使用例を、サンプルコードとして以下に示す。 -LogicalTreeHelperを使用する場合は、以下のPrintLogicalTreeメソッドを実行する。 private void PrintLogicalTree() { Debug.WriteLine("PrintLogicalTree"); PrintLogicalTree(0, this); } // 論理ツリーを出力する。 // DependencyObjectの場合は、子要素も再帰的に表示する private void PrintLogicalTree(int level, DependencyObject obj) { PrintObject(level, obj); foreach (var child in LogicalTreeHelper.GetChildren(obj)) { if (child is DependencyObject) { PrintLogicalTree(level + 1, (DependencyObject)child); } else { PrintObject(level + 1, child); } } } -VisualTreeHelperを使用する場合は、以下のPrintVisualTreeメソッドを実行する。 private void PrintVisualTree() { Debug.WriteLine("PrintVisualTree"); PrintVisualTree(0, this); } // ビジュアル ツリーを表示する。 // DependencyObjectの場合はビジュアル ツリー上の子要素も再帰的に出力していく private void PrintVisualTree(int level, DependencyObject obj) { PrintObject(level, obj); foreach (var child in GetVisualChildren(obj)) { if (child is DependencyObject) { PrintVisualTree(level + 1, (DependencyObject)child); } else { PrintObject(level + 1, child); } } } // ビジュアル ツリーの子要素の列挙を返す private IEnumerable<object> GetVisualChildren(DependencyObject obj) { for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++) { yield return VisualTreeHelper.GetChild(obj, i); } } -共通(結果をインデントつきで出力) // ToStringの結果をインデントつきで出力 private void PrintObject(int level, object obj) { Debug.WriteLine(new string('\t', level) + obj); } **WPFプロパティ システム [#u00b87e5] 本項では、DependencyObjectにより実装される「WPFプロパティ システム」の -「依存関係プロパティ」 -「添付プロパティ」 -「プロパティ値の継承」 について説明する。 なお、それぞれのプロパティの定義方法などについても触れるが、実際にこれらのプロパティを独自に定義する必要がある場合は、カスタム コントロール作成時にあたる 。 -MSDN > Windows Presentation Foundation~ コントロール > コントロールのカスタマイズ > コントロールの作成の概要~ http://msdn.microsoft.com/ja-jp/library/ms745025.aspx ***依存関係プロパティ [#y0f446a9] 「依存関係プロパティ」は、「WPFプロパティ システム」によってサポートされるプロパティで、WPFに管理される一種の辞書構造を用いて値を保持する。「依存関係プロパティ」では、変更監視・有効値検証などの機能が使用可能である。 -MSDN > WPFの基礎 > プロパティ > 依存関係プロパティの概要~ http://msdn.microsoft.com/ja-jp/library/ms752914.aspx -用途~ 「依存関係プロパティ」は、下記で使用されている。 --動的な「リソース」参照 ---「スタイル」 ---「アニメーション」 --「データ バインディング」 --「添付プロパティ」 --「プロパティ値の継承」 -定義~ 「依存関係プロパティ」は、一般的なプロパティであるCLRプロパティのように定義するのではなく、「WPFプロパティ システム」に対し「依存関係プロパティ」として登録する必要がある。 --定義方法~ 以下、「依存関係プロパティ」の定義方法について説明する。 ---public static readonly(VBでは、Public Shared ReadOnly)なDependencyProperty型の変数として宣言する。 ---「依存関係プロパティ」名の末尾に「Property」を付与する(WPFの名称付与基準) ---変数宣言時か、静的コンストラクタを初期化する。~ DependencyProperty.Register メソッドを使用し「依存関係プロパティ」として「WPFプロパティ システム」に登録する。~ http://msdn.microsoft.com/ja-jp/library/system.windows.dependencyproperty.register.aspx ---「依存関係プロパティ」は、プロパティの設定・取得方法が特殊なので、~ CLRプロパティでラップし、プロパティにアクセスし易いようにする。 --実装例~ 以下、「依存関係プロパティ」の定義の実装例を示す。 // 依存関係プロパティを実装するクラス public class ConcreteDependencyObject : DependencyObject { // 依存関係プロパティ public static readonly DependencyProperty CaptionProperty; // 静的コンストラクタ static ConcreteDependencyObject(){ // 静的コンストラクタで依存関係プロパティを登録 CaptionProperty = DependencyProperty.Register( "Caption", // プロパティ名 typeof(string), // プロパティの型 typeof(ConcreteDependencyObject), // プロパティの所有者 new PropertyMetadata()); // 各種メタデータ } // 依存関係プロパティは設定・取得方法が特殊であるので、 // 以下のように、CLRプロパティでラップする。 public string Caption { get { return this.GetValue(ConcreteDependencyObject.CaptionProperty) as string; } set { this.SetValue(ConcreteDependencyObject.CaptionProperty, value); } } } --MSDN > WPFの基礎 > プロパティ ---カスタム依存関係プロパティ~ http://msdn.microsoft.com/ja-jp/library/ms753358.aspx ---XAML読み込みと依存関係プロパティ~ http://msdn.microsoft.com/ja-jp/library/bb613563.aspx -機能~ 「依存関係プロパティ」では、以下のような機能が使用可能になる。 --プロパティの既定値の設定 --ソース プロパティの変更監視コールバックの設定 --プロパティ値の強制コールバックの設定 --プロパティ値の有効値検証コールバックの設定 >なお、以下それぞれの機能の説明と、DependencyProperty.Registerメソッドを使用して「依存関係プロパティ」を登録する際の第4引数に指定するPropertyMetadata クラスと、そのコールバックのコード例を示す。 --プロパティの既定値の設定~ プロパティの既定値を設定する。 new PropertyMetadata("DefaultValue") ---MSDN > .NET Frameworkクラス ライブラリ > System.Windows.PropertyMetadataクラス~ http://msdn.microsoft.com/ja-jp/library/system.windows.propertymetadata.aspx --ソース プロパティの変更監視コールバックの設定~ 「依存関係プロパティ」が、有効なプロパティ値に変更された時に呼び出されるコールバックを設定する。~ 例えば、値を「最小値 ~ 最大値の間に強制する」などの用途で使用するコールバック。 new PropertyMetadata("DefaultValue", new PropertyChangedCallback(OnPropertyChangedCallback)) // プロパティ値の変更監視コールバック private static void OnPropertyChangedCallback( DependencyObject d, DependencyPropertyChangedEventArgs e) { // プロパティ値の変更監視の例: string oldValue = (string)e.OldValue; string newValue = (string)e.NewValue; DependencyProperty dp = e.Property; } ---MSDN > .NET Frameworkクラス ライブラリ > System.Windows.PropertyChangedCallbackデリゲート~ http://msdn.microsoft.com/ja-jp/library/system.windows.propertychangedcallback.aspx --プロパティ値の強制コールバックの設定~ 「依存関係プロパティ」の値が再評価されたり、強制が明示的に要求されたりした場合に呼び出されるコールバックを設定する。 new PropertyMetadata("DefaultValue", new PropertyChangedCallback(OnPropertyChangedCallback), new CoerceValueCallback(OnCoerceValueCallBack)) // 依存関係プロパティ値の強制コールバック private static object OnCoerceValueCallBack(DependencyObject d, object value) { // プロパティ値の強制の例: // Captionプロパティ値に「"ChangeValue"」が設定されない限り // Captionプロパティ値は「"DefaultValue"」を強制する。 if (value.ToString() == "ChangeValue") return value; return "DefaultValue"; } ---MSDN > .NET Frameworkクラス ライブラリ > System.Windows.CoerceValueCallbackデリゲート~ http://msdn.microsoft.com/ja-jp/library/system.windows.coercevaluecallback.aspx --プロパティ値の有効値検証コールバックの設定~ 「依存関係プロパティ」の値が再評価された際、有効値を検証するコールバックを設定する。 new PropertyMetadata("DefaultValue", new PropertyChangedCallback(OnPropertyChangedCallback), new CoerceValueCallback(OnCoerceValueCallBack), new ValidateValueCallback(OnValidateValueCallback)); // プロパティ値の有効値検証コールバック private static bool OnValidateValueCallback(object value) { // プロパティ値の有効値検証の例: // Captionプロパティ値に「" DengerousValue "」が設定されるとエラーになる。 if (value.ToString() == "DengerousValue") return false; return true; } ---MSDN > .NET Frameworkクラス ライブラリ > System.Windows.ValidateValueCallbackデリゲート~ http://msdn.microsoft.com/ja-jp/library/system.windows.validatevaluecallback.aspx ***添付プロパティ [#bb2645d8] 「添付プロパティ」は、「WPFプロパティ システム」によってサポートされるプロパティで、「添付プロパティ」のほとんどが「依存関係プロパティ」として実装される。 -MSDN > WPFの基礎 > プロパティ > 添付プロパティの概要~ http://msdn.microsoft.com/ja-jp/library/ms749011.aspx -用途~ 「添付プロパティ」は、親要素で定義されるプロパティに対し、子要素がそれぞれ別の値を指定するなど、任意のオブジェクトに対して設定可能なグローバル プロパティとして機能する。「添付プロパティ」の代表的な使用例には、「パネル要素」などの子要素を格納する親要素が、子要素のレイアウトを制御するための各プロパティがある。 >ここでは、 -親要素として、Canvas要素 -子要素として、TextBlock要素 >を例に挙げて説明する。 >TextBlockのレイアウトを制御するため、TextBlockに(仮に)CanvasTop、CanvasLeftプロパティを持たせた場合、TextBlockが、Canvas要素の子要素ではない場合、無駄なデータを持つことになる。この問題を解決するため、「添付プロパティ」は、親要素が子要素の動作を制御するためのプロパティを子要素から指定可能な一種のグローバル プロパティとして実装する。以下は、レイアウトを制御するCanvas要素の「添付プロパティ」であるCanvas.Top、Canvas.Leftプロパティへ、XAMLからTextBlock要素から値を設定する方法である。~ <Canvas> <TextBlock Canvas.Top="10" Canvas.Left="20"> Hello World! </TextBlock> </Canvas> >子要素から親要素への「添付プロパティ」設定の際、内部的には「添付プロパティ」のアクセッサ メソッド(後述)のキーに子要素が指定される。 -定義~ 「添付プロパティ」を定義する場合は、「依存関係プロパティ」と異なり、DependencyProperty.Registerメソッドではなく、DependencyProperty.RegisterAttached メソッドを使用し「添付プロパティ」として登録する。 --MSDN > WPFの基礎 > プロパティ > 方法:添付プロパティを登録する~ http://msdn.microsoft.com/ja-jp/library/ms753957.aspx ---MSDN > .NET Frameworkクラス ライブラリ > System.Windows.DependencyProperty.RegisterAttachedメソッド~ http://msdn.microsoft.com/ja-jp/library/system.windows.dependencyproperty.registerattached.aspx >また、「添付プロパティ」はCLRプロパティ ラッパではなく、 -Get(プロパティ名) -Set(プロパティ名) >の名称付与基準に従った、専用の静的 get、setアクセッサ メソッドを実装する必要がある。~ public static void Setプロパティ変数名(UIElement element, Boolean value) { element.SetValue(this.プロパティ変数, value); } public static Boolean Getプロパティ変数名(UIElement element) { return (Boolean)element.GetValue(this.プロパティ変数); } >これらのアクセッサ メソッドは、XAMLリーダが「添付プロパティ」をXAMLの属性として認識し、適切な型を解決できるようにするために必要となる。コードビハインドから、これらのアクセッサ メソッドを使用して「添付プロパティ」を設定する際は、キーに子要素を指定する。~ <Canvas x:Name="myCanvas"> </Canvas> TextBlock textBlock = new TextBlock(); textBlock.Text = "Hello World!"; // 添付プロパティを設定 Canvas.SetTop(textBlock, 10); Canvas.SetLeft(textBlock, 20); this.myCanvas.Children.Add(textBlock); ***プロパティ継承(包含継承) [#qaec881f] 「WPFプロパティ システム」では、包含継承(HTMLコードと同様に、親要素に書いた属性値が子要素に継承される。HTMLでは、例えば、body要素に対してstyle属性やfont属性でフォント・サイズを指定すると、body要素内のすべての要素のフォント・サイズが変化する。※ 注:オブジェクト指向プログラミングにおける継承(派生クラスがその基本クラスからメンバ定義を継承する)とは異なる概念。)をサポートしている。 これを実現するのが「プロパティ値の継承」の機能である。「プロパティ値の継承」がされる一部のプロパティは、「要素ツリー」の最も近い親要素から特定のプロパティの値を継承し、親要素のプロパティ値が変更された場合、自動的に子要素に反映する。この動作は、子要素から親要素のプロパティを設定する「添付プロパティ」と逆の働きであるため、「プロパティ値の継承」の仕組みも、「添付プロパティ」と同様の方式で実装されていることが分かる(そのため、「添付プロパティ」と同様、プロパティの登録にDependencyProperty.RegisterAttachedメソッドを使用する)。 -MSDN > WPFの基礎 > プロパティ > プロパティ値の継承~ http://msdn.microsoft.com/ja-jp/library/ms753197.aspx -用途~ 包含継承の機能は、親要素、例えば、ルート要素(Window or Page)に一度だけ定義することで、画面全体のポリシーを統一するようなプロパティに適している。「プロパティ値の継承」がされるプロパティの一例として、以下のものがある。 --Control.FontSizeプロパティ --FrameworkElement.FlowDirectionプロパティ.etc -定義~ DependencyProperty.RegisterAttachedメソッドの第4引数に指定するPropertyMetadata(FrameworkPropertyMetadata)クラスのオプション 設定で、「プロパティ値の継承」を可能に設定する。 --MSDN > WPFの基礎 > プロパティ > プロパティ値の継承 - カスタム プロパティを継承可能にする~ http://msdn.microsoft.com/ja-jp/library/ms753197.aspx#Making_a_Custom_Property_Inheritable なお、「プロパティ値の継承」のブロッキング境界として、Frameなどのコントロールを使用できる。 **データ バインディング [#dac6f2bf] WPFでは、ビュー(XAML:データの表示)とモデル(コードビハインド:チェック処理や、データアクセス処理などアプリケーションの処理)を分離するための仕組みとして、「データ バインディング」という機能を提供している。これには、前述の「依存関係プロパティ」を使用している。 -「データ バインディング」を利用すれば、ビューとモデルの接点を、任意のプロパティ接続だけに限定できる。このため、ビューの内部にビューとモデルを接続するロジックを持つ必要が無くなり、ビュー内のコード量を削減すると同時に疎結合を実現できる。 -「データ バインディング」により、2つのオブジェクトを結合するが、通常、ビュー側のXAMLで生成されたCLRオブジェクトを「バインディング ターゲット」(=結合先)、モデル側のコードビハインドで生成されたCLRオブジェクトを「バインディング ソース」(=結合元)と呼ぶ。この2つのオブジェクトを結合するためにBinding オブジェクトを使用する。 -なお、「バインディング ターゲット」へ渡される、「バインディング ターゲット」に入力されたデータや、「バインディング ソース」の更新通知によるデータの妥当性検証の機能は、(継承する)DependencyObjectにより提供される。この「バインディング ソース」からの更新通知の機能は、(実装する)INotifyPropertyChangedインターフェイスにより提供される。それぞれ、これに合わせた実装が必要になる。 このため、「データ バインディング」の機能は、 -ビュー側「バインディング ターゲット」のDependencyObjectオブジェクト --System.Windows.DependencyObjectクラス~ https://msdn.microsoft.com/ja-jp/library/system.windows.dependencyobject.aspx -モデル側「バインディング ソース」のINotifyPropertyChanged インターフェイス --System.ComponentModel.INotifyPropertyChangedインターフェイス~ http://msdn.microsoft.com/ja-jp/library/system.componentmodel.inotifypropertychanged.aspx -上記2つの要素を結び付けるBindingオブジェクト --System.Windows.Data.Bindingクラス~ https://msdn.microsoft.com/ja-jp/library/system.windows.data.binding.aspx の3つの要素によって提供されると言って良い。 -連載 WPF/Silverlight UIフレームワーク入門:~ 第2回 データの表示と入力に必要な知識 (1/5) - @IT~ http://www.atmarkit.co.jp/ait/articles/0905/19/news145.html ***「データ バインディング」のプロパティ [#y87c2f7b] Bindingクラスが持つ主要なプロパティ |項番|プロパティ|説明|h |1|Mode|データが反映される方向を、以下の列挙型から選択して指定する。&br;・OneWay:「バインディング ソース」変更時、「バインディング ターゲット」を更新する。&br;・OneWayToSource:「バインディング ターゲット」変更時、「バインディング ソース」を更新する。&br; ※ WPFのみで、「Silverlight」には無いモード&br;・TwoWay:「バインディング ソース」、「バインディング ターゲット」が変更された場合、対応する「バインディング ターゲット」、「バインディング ソース」を更新する。&br;・OneTime:アプリケーション起動時のみ、「バインディング ターゲット」のデータを更新(StaticResourceに接続する場合などに使用する)&br;・Default:「バインディング ターゲット」の既定のModeとなる。&br; ※ WPFのみで、「Silverlight」には無いモード| |2|Source|「バインディング ソース」を指定する。| |3|Path|「バインディング ソース」のプロパティ名を指定する(名前空間のフルパスで指定可)。| ***XAMLで「データ バインディング」を実装 [#db619849] 「データ バインディング」は、XAML上の要素のプロパティ値として「バインディングのマークアップ拡張」である「{Binding ・・・}」という記述を使用してBindingオブジェクトを生成・初期化することで実装する。 ***DataContextの使用 [#v92c0074] -MSDN > .NET Frameworkクラス ライブラリ > FrameworkElement.DataContextプロパティ~ http://msdn.microsoft.com/ja-jp/library/system.windows.frameworkelement.datacontext.aspx -「バインディング ソース」と「バインディング ターゲット」の数が増え、それぞれのオブジェクト間のマッピングが面倒な場合、~ Bindingオブジェクトの規定のターゲットであるDataContextプロパティに「バインディング ソース」を設定することで、Bindingオブジェクトへの「バインディング ソース」の指定が不要になる。 -「データ バインディング」では、「バインディング ターゲット」と「バインディング ソース」が、リフレクションによるプロパティ名にて結び付けられている。このため、FrameworkElement.DataContextプロパティに、任意のカスタム型を渡すことができる。 -なお、DataContextプロパティは、「プロパティ値の継承」に対応しているため、指定した「バインディング ソース」は、親要素から子要素に継承されるので、親要素(もしくは自身)のDataContextプロパティに「バインディング ソース」を1回指定すればよい。 ***暗黙的な型変換 [#w78d8241] また、「データ バインディング」では、「バインディング ターゲット」と「バインディング ソース」でプロパティ型が異なる場合、暗黙的な型変換が行われる。 -型変換の動作のカスタマイズ --暗黙の型変換(または値変換)が失敗する場合、nullが返される。この対応としてIValueConverter インターフェイスを実装した「値コンバータ」を実装することで明示的な型変換(または値変換)が可能になる。なお、「値コンバータ」で型変換できない場合も同様に、nullを返すように実装する。nullが返された場合、通常は何も表示されないが、これをカスタマイズする場合は、Binding.TargetNullValueプロパティを実装し、ソース値が nullのときに返される値を指定する。 --その他の用例 ---暗黙の型変換が失敗する場合 ---例えば、入力数値から背景色を変更するような場合 ***色々なデータ バインディングのパターン [#p660eac3] -(1) --コードビハインドからのデータ バインディング(モード:OneWay) ---「データ バインディング」の基本的な動作を理解するために、Bindingオブジェクトをコードビハインドで自作し、「バインディング ソース」と「バインディング ターゲット」の2つのオブジェクトを結び付け、モード:OneWayの「データ バインディング」を行う。 ---UI要素の表示に関するプロパティは、基本的に「依存関係プロパティ」として実装されており、既定で変更通知をサポートしている。このため、既定で双方向接続が可能である。 --コードビハインドからのDataContextを使用したデータ バインディング(モード:OneWay)~ DataContextを使用してデータ バインディングをする。 -(2) --変更通知の追加(モード:OneWay & OneWayToSource)~ OneWay の「バインディング ソース」には、INotifyPropertyChangedインターフェイスを実装して、プロパティ値の変更通知処理を実装する必要がある。 --値コンバータの使用(モード:OneWay & OneWayToSource)~ モード:OneWay & OneWayToSourceを併用した「データ バインディング」は、「バインディング ソース」のプロパティ値の変更(入力)を、自動的に「バインディング ターゲット」に反映(出力)できる。 -(3) --双方向のデータ バインディング(モード:TwoWay)~ OneWay & OneWayToSourceをTwoWayで実装。 --値コンバータの使用(モード:TwoWay)~ OneWay & OneWayToSourceをTwoWayで実装。 -(4) --ItemsSourceへのデータ バインディング~ ItemsControlから派生した要素のItemsSource属性にコレクションを「データ バインディング」する場合、対象オブジェクトは反復処理をサポートしている必要がある。 --インデクサによるデータ バインディング~ XAMLの「バインディングのマークアップ拡張」にて、BindingプロパティであるPath属性に角括弧を指定することで、インデクサを使用して接続可能である。 **ルーティング イベント [#m1474b2f] イベントを生成したUIコントロール上だけでなく、「ビジュアル ツリー」内の複数のリスナ上でイベント ハンドラを呼び出すことができるWPFのイベント。例えば、Buttonコントロールが「テンプレート」を使用し、複数のコントロールから構成される場合、下位のコントロールのイベントを上位のButtonコントロールでもハンドルできる。 -MSDN > WPFの基礎 > イベント(WPF) > ルーティング イベントの概要~ http://msdn.microsoft.com/ja-jp/library/ms742806.aspx ***ルーティング方法 [#jd3aaeae] 「ルーティング イベント」は、3つのルーティング方法のいずれかを使用する。 |項番|区分|機能|h |1|トンネル|ツリーを下方向へ辿る。&br;最初に、「ビジュアル ツリー」のルートのイベント ハンドラが呼び出され、次に、イベントを発生させた要素に到達するまで、「経路」沿いの「トンネル ルーティング イベント」のイベント ハンドラを呼び出す。なお、「トンネル ルーティング イベント」のイベント名は、先頭に「Preview」を付与するルールとなっている。| |2|バブル|ツリーを上方向へ辿る。&br;最初に、イベントを発生させた要素のイベント ハンドラが呼び出され、次に、「ビジュアル ツリー」のルートに到達するまで、「経路」沿いの「バブル ルーティング イベント」のイベント ハンドラを呼び出す。| |3|直接|イベントを発生させた要素のみに、イベント ハンドラを呼び出す機会が与えられる。 これは、Windows フォームのイベントと似ている。ただし、標準のCLRイベントとは異なり、「クラス処理」をサポートする。| -MSDN > WPFの基礎 > イベント~ ルーティング イベントの処理済みとしてのマーキング、およびクラス処理~ http://msdn.microsoft.com/ja-jp/library/ms747183.aspx 多くの場合、WPF から提供される入力イベントは、「トンネル ルーティング イベント」 / 「バブル ルーティング イベント」ペアとして実装される。 ***通常の使い方 [#oc007e5d] イベントを発生元の要素で処理する限り、「ルーティング イベント」の動作はあまり表面には見えないので、イベントが「ルーティング イベント」として実装されていることに気を配る必要はない。 これは、「ルーティング イベント」は、共通ハンドラを定義する場合や、カスタム コントロールを複合化する場合などの、「特定のシナリオ」で効果を発揮するためである。例えば、以下は、Buttonコントロールのイベントを発生元の要素で処理するイベント ハンドラを実装する例である。この場合、WPFのデザイナにButtonコントロールをD & Dし、これをダブル クリックすることで、発生元の要素で処理するButton.Clickイベント ハンドラを実装できる。 -XAML~ <Grid> <Button Height="23" Name="button1" Click="button1_Click">Button</Button> </Grid> -コード ビハインド~ public partial class Window1 : Window { public Window1() { InitializeComponent(); } private void button1_Click(object sender, RoutedEventArgs e) { // button1_Click } } ***イベントの追加方法 [#o2b73970] -XAML~ XAMLでは、イベント リスナである要素の属性にイベント ハンドラを指定することで、「型コンバータ」により、イベント ハンドラを設定できる。上記のClick="button1_Click"が、それに該当する。 -コード ビハインド~ なお、イベントの指定をXAMLの「型コンバータ」からではなく、コード (C#) から指定する場合は、次の2種類の方法(メソッド、演算子)で行うことができる。 --UIElement.AddHandlerメソッドを利用する場合: this.button1.AddHandler(Button.ClickEvent, new RoutedEventHandler(button1_Click)); --オーバーロードされた演算子を利用する場合: this.button1.Click += new RoutedEventHandler(button1_Click); ***サンプル [#m7ba51ae] 下記のXAMLは、 -「トンネル ルーティング イベント」:PreviewMouseDownイベント -「バブル ルーティング イベント」:MouseDownイベント の動作を確認するためのサンプル。 -論理ツリー~ StackPanel - Border - Rectangle -XAML~ <StackPanel x:Name="stackPanel1" Height="100" Width="100" Orientation="Vertical" MouseDown="stackPanel1_MouseDown" PreviewMouseDown="stackPanel1_PreviewMouseDown"> <Border x:Name="border1" MouseDown="border1_MouseDown" PreviewMouseDown="border1_PreviewMouseDown"> <Rectangle x:Name="rect1" Height="100" Width="100" Fill="Black" MouseDown="rect1_MouseDown" PreviewMouseDown="rect1_PreviewMouseDown"> </Rectangle> </Border> </StackPanel> -コード ビハインド~ /// <summary>stackPanel1のMouseDownイベント</summary> private void stackPanel1_MouseDown(object sender, MouseEventArgs e) { System.Diagnostics.Debug.WriteLine("→ stackPanel1_MouseDown"); } /// <summary>stackPanel1のPreviewMouseDownイベント</summary> private void stackPanel1_PreviewMouseDown(object sender, MouseEventArgs e) { System.Diagnostics.Debug.WriteLine("→ stackPanel1_PreviewMouseDown"); } /// <summary>border1のMouseDownイベント</summary> private void border1_MouseDown(object sender, MouseEventArgs e) { System.Diagnostics.Debug.WriteLine("→ border1_MouseDown"); } /// <summary>border1のPreviewMouseDownイベント</summary> private void border1_PreviewMouseDown(object sender, MouseEventArgs e) { System.Diagnostics.Debug.WriteLine("→ border1_PreviewMouseDown"); } /// <summary>rect1のMouseDownイベント</summary> private void rect1_MouseDown(object sender, MouseEventArgs e) { System.Diagnostics.Debug.WriteLine("→ rect1_MouseDown"); } /// <summary>rect1のPreviewMouseDownイベント</summary> private void rect1_PreviewMouseDown(object sender, MouseEventArgs e) { System.Diagnostics.Debug.WriteLine("→ rect1_PreviewMouseDown"); } このコードを実装して、画面上のRectangleをクリックすると、以下のようなDebug出力を確認でき、この出力から「トンネル ルーティング イベント」 / 「バブル ルーティング イベント」ペアが正しく動作していることを確認できる。 stackPanel1_PreviewMouseDown → border1_PreviewMouseDown → rect1_PreviewMouseDown → rect1_MouseDown → border1_MouseDown → stackPanel1_MouseDown なお、各イベント ハンドラで「e.Handled = true」を実行すると、ルーティングは停止する。例えば、「トンネル ルーティング イベント」でルーティングを停止すれば、「バブル ルーティング イベント」も発生しなくなる。 *WPFのコントロール [#zc4549e3] **標準コントロール [#te4c8df4] WPFは、次のような標準コントロールを備えている。 -MSDN > Windows Presentation Foundation~ 移行と相互運用性 > Windowsフォーム コントロールおよび同等のWPFコントロール~ http://msdn.microsoft.com/ja-jp/library/ms750559.aspx ***コントロール(Control) [#h4d56350] ボタンやリストボックスなどのコントロール類 一例 -Label -TextBox -Button -ComboBox -ListBox -DataGrid ***パネル(Panel) [#c22bceea] 子要素の配置を決める。 一例 -Canvas -DockPanel -StackPanel -WrapPanel -UniformGrid -Grid ***シェイプ(Shape) [#fb5fcbd0] ベクタグラフィックスを描画 一例 -Rectangle -Ellipse -Path ***メディア(FrameworkElement) [#e0214f36] 静止画や動画などの表示 一例 -Image -MediaElement ***ドキュメント(TextBoxBase) [#y2c63538] 文書整形 一例 -RichTextBox **ユーザ コントロール [#m9448a6a] ユーザ コントロールは、UI要素の部品化を目的としたもので、Windowsフォーム、ASP.NETアプリケーション(Webフォーム)などと同様に、ユーザ コントロールの開発・使用が可能である。 -MSDN > Windows Presentation Foundation > コントロール~ コントロールのカスタマイズ > コントロールの作成の概要~ http://msdn.microsoft.com/ja-jp/library/ms745025.aspx WPFでは、ユーザ コントロールのCLRプロパティを初期化する場合、XAML要素から指定可能であったり、ユーザ コントロール内の各コントロールに「データ バインディング」する場合は、ユーザ コントロールのDataContextプロパティに「バインディング ソース」を指定可能であったり、また、「ツールチップ」の表示にユーザ コントロールを設定したりするなど、ユーザ コントロールをより柔軟に利用できる。 ***画面遷移での利用 [#kd27bd58] -ユーザ コントロールをプログラムからインスタンス化して、(ナビゲーション フレームワークの仕様に依らず)画面遷移やダイアログの代替を実現したりできる。 -ダイアログがサポートされていない「XBAP」で、z-indexを適切に設定するか、最後の要素としてルートのパネル要素に追加することで、ダイアログ表示の代替が可能(Silverlight ver3から、ChildWindowコントロールが利用できる)。 -ユーザ コントロールにアニメーションを適用することで、アニメーション効果付の画面遷移を実装することができる。 ***部品の汎用化 [#pd716aa3] ユーザ コントロールのプロパティを以下の用途で使用する場合、それぞれ追加の実装が必要になるので注意する。 -変更通知を実装した「バインディング ソース」として使用する場合、~ INotifyPropertyChangedインターフェイス、変更通知処理を実装する必要がある。 -変更監視・有効値検証を実装した「バインディング ターゲット」として使用する場合、~ DependencyObjectクラスを継承し、「依存関係プロパティ」として実装する必要がある。 *[[XAML]] [#p410257d]