WPF ベータ2における境界フィードバックについて

今回は、前回のイナーシアで説明が不足していた境界フィードバックについて説明します。基本的には、前回に提示したコードを使用します。最初にManipulationDeltaイベントハンドラに記述したコードをもう一度、以下に提示します。 // マニピュレーションコンテナの四角形を取得します Rect containingRect = new Rect(((FrameworkElement) e.ManipulationContainer).RenderSize); // 移動後のUI要素の軸並行境界を含む四角形を取得します Rect shapeBounds = element.RenderTransform.TransformBounds( new Rect(element.RenderSize)); // マニピュレーションコンテナの境界を越えたら // イナーシアの操作を停止します if (e.IsInertial && !containingRect.Contains(shapeBounds)) { e.Complete(); e.ReportBoundaryFeedback(e.DeltaManipulation); } 上記のコードから、e.Complete()を削除して実行してみてください。これでReportBoundaryFeedback(境界フィードバック)の動きが理解できると思います。実際に試すと、描画領域の四隅がブルブルと動くのを確認することができます。これは、WPF4のイナーシアにおいて境界フィードバックを行うことでウインドウ自体が操作した方向へ引っ張られるような効果を視覚に訴えるためだと考えられます。 これだけだと面白くないので、以下のようなメソッドを追加してみます。 // 移動ベクターを計算します private Vector CalculateOvershoot(UIElement element) { // 要素の軸平行境界ボックスを取得します(実際の描画コレクションの軸平行境界を使用します) var elementBounds = element.RenderTransform.TransformBounds( VisualTreeHelper.GetDrawing(element).Bounds); double extraX = 0.0, extraY = 0.0; // 座標xを計算します 上と左側が跳ね返ります…


WPF4 ベータ2 におけるイナーシアについて

今回は、WPF4ベータ2のイナーシア(慣性)を説明します。イナーシアは慣性という日本語訳をしますが、なぜ慣性というかといえば、タッチした動作に基づいて運動量の強弱を表現するからです。Windows SDK に記載されている運動量のグラフが以下になります。 このグラフをみると、Velocityが時間の経過とともに減衰するのがわかります。このような時間経過に伴う運動量の増減を処理するために、Win32 API では InertiaProcessor が用意されています。 イナーシアの動作を理解するためには、以下のような動きを実現することだと理解すれば良いでしょう。 この図に表現しているボーダーやエラスティックマージン(跳ね返る領域を定義するマージン)とは、Win32APIで定義されているものになります。 WPF4ではManipulation と Inertia が統合されており、Inertiaを実現するには以下のようなXAMLを記述します。 <Window x:Class=”Inertia.MainWindow” xmlns=”http://schemas.microsoft.com/winfx/…/presentation” xmlns:x=”http://schemas.microsoft.com/…/xaml” Title=”イナーシア サンプル” Height=”500″ Width=”600″ WindowStartupLocation=”CenterScreen” WindowState=”Normal” > <Canvas x:Name=”canvas” ManipulationStarting=”canvas_ManipulationStarting” ManipulationDelta=”canvas_ManipulationDelta” ManipulationInertiaStarting=”canvas_ManipulationInertiaStarting”> <Image IsManipulationEnabled=”True” x:Name=”image1″ Width=”200″ Source=”Guitar.jpg”> <Image.RenderTransform> <MatrixTransform /> </Image.RenderTransform> </Image> </Canvas> </Window> 上記のXAMLで理解できますが、Manipulationの時に記述したイベントハンドラであるManipulationStartingとManipulationDeltaに続いて、ManipulationInertiaStartingイベントハンドラを追加しています。このManipulationInertiaStarting イベントハンドラで慣性の動きである運動量の減衰値を設定します。このイベントハンドラの具体例を説明する前に、WPFにおけるイベントの発生順序を以下に示します。 上記の上側に表現しているTouchDown、TouchMove、TouchUpは、生のタッチイベントになります。タッチイベントが発生してから、Manipulationに関係するイベントであるManipulationStartingやManipulationDeltaが発生して、タッチアップかManipulationDeltaイベントからManipulationInertiaStartingイベントが発生し、Inertiaに対応するManipulationDeltaイベントが発生することを表しています。そしてInertiaの終了時にCompletedイベントが発生します。このようにイベントが発生するため、ManipulationDeltaEventArgsに IsInertiaプロパティが用意されています。 MSDNライブラリに掲載されているウォークスルーを使って、イベントハンドラのコードを以下に示します。 private void canvas_ManipulationStarting(object sender, ManipulationStartingEventArgs e) { //…


WPF4 ベータ2におけるマニピュレーションピボットについて

前回は WPF4 ベータ2のマニピュレーションを説明しました。今回は、マニピュレーションピボットを説明します。前回のマニピュレーションを実際に作成して試した方には理解できますが、ジェスチャー操作した場合のオブジェクトの動きは、ジェスチャー動作の中心点からの移動量がManipulationDeltaイベントで処理しています。このため操作対象のオブジェクトに対する中心点に対しての操作とは限らないのです。これに対して操作対象オブジェクトのある点を中心(たとえば中心点など)にマニピュレーション操作を行いたい場合に利用するのが、ManipulationPivotオブジェクトになります。具体的にどうするかといえば、前回のXAMLに対するコードを以下のように記述します。 private void canvas_ManipulationStarting(object sender, ManipulationStartingEventArgs e) { // コンテナの設定 e.ManipulationContainer = canvas; // ピボットの初期化 e.Pivot = GetCenterPivot(e.OriginalSource); e.Handled = true; } // ManipulationPivotを取得します private ManipulationPivot GetCenterPivot(object o) { var element = (UIElement)o; var elementBounds = element.RenderTransform.TransformBounds( VisualTreeHelper.GetDrawing(element).Bounds); // 中心位置を設定したピボット Point center = new Point( (elementBounds.Left + elementBounds.Right) / 2, (elementBounds.Top + elementBounds.Bottom)…


WPF4 ベータ2 における マニピュレーション イベント

.NET Framework 4 RCがリリースされましたが、ベータ2ベースにおける WPF のマルチタッチ対応の1つである、マニピューレーションを取り上げます。マニピュレーションを具体的に説明する前に、Windows 7におけるマルチタッチのWindow メッセージをを説明します。Windowsメッセージには、以下の2つが存在します。 WM_Touch:タッチ、移動、タッチアップという低レベルのメッセージ WM_Gesture:タッチした動作によってどのような操作をしたいかを解釈するメッセージ Windows 7 の標準的なマルチタッチメッセージは、WM_Gestureになります。ジェスチャの基本的な操作は、パン(移動)、ズーム(拡大、縮小)、ローテート(回転)になります。 このジェスチャ操作が、Windows 7 製品版から1本の指でも可能なようになっています。このジェスチャメッセージに対応して、操作しようとする対象(オブジェクト)を簡単に操作するためにManipulationProcessorとInertiaProcessorがWin32APIでは提供されています。この機能に対応するのが、WPF 4 の Mnipulation イベントとなります。このイベントを記述したXAMLを以下に示します。 <Window x:Class=”Manipulation.MainWindow” xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation” xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml” Title=”マニピュレーション″ Height=”500″ Width=”600″ <Canvas x:Name=”canvas” ManipulationStarting=”canvas_ManipulationStarting” ManipulationDelta=”canvas_ManipulationDelta” > <Image IsManipulationEnabled=”True” x:Name=”image1″ Width=”200″ Source=”Guitar.jpg”> <Image.RenderTransform> <MatrixTransform /> </Image.RenderTransform> </Image> </Canvas> </Window>Canvasで記述している ManipulationStarttingイベントとManipulationDeltaイベントがManipulationを行うために必要なイベントハンドラになります。また、Imageオブジェクトに記述している IsManipulationEnabled=”True” という設定が、どのオブジェクトをManipulationイベントで操作するかということを表します。したがって、IsManipulationEnabledは、Manipulationで操作したいオブジェクトが複数あれば、対象毎に設定します(よくある、複数の写真を操作するのであれば写真のイメージ毎に設定します)。 WPF4でManipulation操作をするためには、Manipulationコンテナという考え方を理解しておく必要があります。Manipulationコンテナとイベントの関係を以下に示します。   Manipulation コンテナとは、Manipulation操作を行う領域(上のXAMLでは Canvasオブジェクト)になります。そしてManipulationStartingイベントで、Manipulationコンテナを明示的に設定する必要があります。次に、ManipulationDeltaイベントで実際の操作を行うのです。このイベントハンドラを記述したコードを以下に示します。 private void canvas_ManipulationStarting(…


WPF4 ベータ2 におけるタッチイベント

WPF 4 ベータ2のマルチタッチ対応の1つである、タッチイベントを取り上げます。ドキュメントを読むと、タッチイベントとして、以下のようなものがUIElement クラスに追加されています。 TouchDown:タッチされた場合に発生する。 TouchMove:タッチした指を移動した場合に発生する。 TouchUp:タッチした指を離す場合に発生する。 これ以外にも、PreviewTouchDown,Move,Upというイベントが定義されています。このイベントを使ったXAMLを以下のように定義します。 <Window x:Class=”TouchEventSample.MainWindow”     xmlns=”http://… /2006/xaml/presentation” xmlns:x=”http://…/winfx/2006/xaml” Title=”タッチイベント サンプル” Width=”500″ Height=”300″> <Canvas x:Name=”canvas” Background=”LightYellow” TouchDown=”Canvas_TouchDown” TouchMove=”Canvas_TouchMove” TouchUp=”Canvas_TouchUp” /> </Window> Canvas 定義に、TouchDown、TouchMove、TouchUpイベントを定義しています。これらに対応するコードを以下のように記述します。 public partial class MainWindow : Window { // ブラシのリスト static List _brushes = new List<Brush>() { Brushes.Red, Brushes.Blue,Brushes.Green, Brushes.Purple, Brushes.Pink, Brushes.Orange }; // 次に使用するブラシのインデックス static int _nextBrush =…


[TechDays].NET Framework 4 時代の言語を担当します

Tech・Days 2010では、「.NET Framework 4時代の言語」というセッションを担当します。概要にも記載していますが、扱うテーマは以下の3つになります。 Dynamic (動的) Declarative (宣言型) Concurrent (同時実行) 最初のテーマであるDynamicについては、DLRが提供されることで何ができるかというのがメインテーマになります。ここでお見せする予定のデモとしては、C#<->IronPython、C#<->IronRubyなどの静的言語と動的言語間の相互利用になります。両方を組み合わせることで、どういうことが実現できるかについて説明ができればと考えています。 2番目のテーマとしては、宣言型プログラミングの定義に従って XAML と Visual F#を取り上げます。XAMLについては、.NET Framework 4で提供される System.Xamlを説明する予定です。 F#は、関数型言語としての基本的な部分をご説明することを考えています。 3番目のテーマに関しては、これが一番難しいと感じています。Concurrentという単語を「同時実行」と訳していますが、「並行」と訳す場合もあります。Parallelという単語では、並列と訳するわけです。一般的に並列プログラミングと呼んでも、並行プログラミングと呼ばれることは少ないわけです。並列か並行かというのは、言葉の定義が大切なのですが、並列プログラミングに関するトピックはMSDN ライブラリの中では、Advanced Topicになっているため、一般の人には理解しにくいのではないかと考えています。従って、どのように説明するかという点に関しては、未だに検討しています。 すべてのテーマに関して考えていますのは、 今迄がどうだったのか .NET Framework 4 でどうなるのか ということです。たとえば、Dynamicですが今迄は提供されていませんでしが、これからは提供されるわけです。そうすると、モックオブジェクトと本番オブジェクトを入れ替える場合に「Dynamic」を使うことで依存性を気にしないで入れ替えることが可能になります。もちろんプログラミング的には、インターフェース継承などを使って入れ替える方が、記述ミスの少ないプログラムを記述できますし、実行速度も速くなります。ですが、オブジェクトのインスタンスを作成するFactoryクラスなどを用意する必要があるわけです。これをDynamicにすることで、FactoryクラスがDynamicオブジェクトを返すことで、どのようなオブジェクトでも扱えるようになるわけです。もちろん、知らないメンバーを呼び出すことはコストがかかりますので、呼び出すメンバーの名前に関しては知っている必要がありますが、インターフェースを使うことなく実行時に解決できるのが、DLRのメリットになります。また、2度目以降の呼出しは、サイトバインダーによってキャッシュされていますから、速度の向上も望めるわけです。Dynamicを使用しなかった場合との違いは、「コンパイル時にメンバーを解決するか」「実行時に文字列でメンバーを解決するか」ということです。 この速度面の課題を許容するのなら、オブジェクトを作成するコンテナとしてDLRを活用する価値があるのではないかと、私は考えています。スクリプト系の言語が、色々なところで使われている状況を考えると、使っても問題ないと考えることができます。もちろん、絶対的に速度を重視する場合では、目的を達成するために別の手段をつかうべきだと思います。 PS.考えることが多くて、資料を読み込むのも大変な状況にいます。


XAP をオンデマンドで読み込みには

Silverlight 4ベータSDKには、Managed Extensibility Framework(MEF)が含まれています。MEFを簡単に説明するとすれば、Composite Application を作成するためのフレームワークで、最新のモノはCodePlexで公開されています。このMEFとSilverlight Toolkitに含まれるSystem.ComponentModel.Coposition.Packaging.Toolkit.dllを組み合わせると、別のXAPをダウンロードして複合化(Composition)アプリケーションに仕上げることができます。このPackaging.Toolkitに含まれるPackageクラスを使って、自分で外部のXAPを読み込む方法をご紹介します。外部のパッケージを読み込むには、以下のようなコードを記述します。  Package package; // イベントハンドラ private void btnDownload_Click(object sender, RoutedEventArgs e) { Uri uri = new Uri(“ExternalXap1.xap”, UriKind.Relative); Package.DownloadPackageAsync(uri, (args, p) => package = p ); }   PackageクラスのDownloadPackageAsyncメソッド呼び出せば、ラムダ式に記述したようにpackage変数にダウンロードしたXAPに関する情報が格納されます。格納されたPackageクラスのインスタンスには、以下のようなプロパティがあります。 Uriプロパティ:指定したXAPのUriです。 Assemblies:XAPに含まれるAppManifest.xamlのAssemblyPartで定義されているアセンブリをインスタンス化したコレクションです。 Packageクラスのインスタンスが手に入れば、クラスのインスタンスを作成するには以下のようにします。  foreach (var asm in package.Assemblies) { // 該当するアセンブリを見つけた場合 object obj = asm.CreateInstance(“クラス名”); // 作成したインスタンスを使って何かの処理を行います } このPackageクラスのDownloadPackageAsyncメソッドを調べると以下のようなことを行っているのを理解することができます。 WebClientクラスを使ってXAPの読み込み。…


Silverlight3 での WCF エラーの扱い方について

昨日は、わんくま同盟の勉強会に参加していました。ここであった質問に、Silverlight で WCFサービスのエラーを処理するにはどうしたら良いかというものがありました。基本的には、SDKドキュメントに記述があるのですが、なかなか知られていないのかなと思いました。 Silverlight 3で WCFのエラーを処理するには、WCFサービス側でビヘイビアを実装する必要があります。このビヘイビアでは、以下の2つの機能を実装する必要があります。 HTTPステータスを「200OK」に変更する。 SDKでは、SilverlightFaultMessageInspector.BeforeSendReplyメソッドで行っています。 ApplyDispatchBehaviorメソッドで、MessageInspectorsにSilverlightFaultMessageInspectorを追加する。 カスタムビヘイビアの準備ができたら、サービス側のエンドポイントビヘイビアに組み込みます。 サービスが出来上がれば、Silverlight側ではCompletedメソッドにエラー処理を組み込めば完了です。この場合は、try catchでエラーを補足するのではなく、イベント引数のErrorプロパティを使用します。「FaultExeption<ExceptionDetail> falut = e.Error as FaultExeption<ExceptionDetail>」のようにFaultExceptionへキャストしてから、Detailプロパティを使ってエラー内容にアクセスすることができるようになります。 WCFサービス側でエラー用のカスタムベヘイビアを作成していない場合は、HTTPステータスが500で返ってきます。この場合は、try catchでエラーを補足できますが、CommunicationExceptionとしか認識することができません。この理由から、HTTPステータスを200OKにする必要があります。Silverlight2の場合も考え方は同じなのですが、 FaultExeptionクラスなどがSilverlight3ほど用意されていませんので、自分で実装する必要がありました。 これらの理由は、Silverlight向けのWCF実装が.NET Framework向けのサブセットであり機能を縮小しているからです。WCFのフルセットであれば、try catchでエラーを補足してSOAP例外を取り出すことができますが、Silverlight向けのサブセットには含まれていないためです。


DLR プロジェクトの状況 2010年1月時点

久し振りにDLRの状況を記述したいと思います。2010.1時点では、以下のようなものがリリースされています。 IronPython 2.6 (2009.12.11) IronPython 2.6 CTP .NET 4.0 Beta2 (2009.10.21) IronRuby 1.0 RC1 (2009.11.20) IronRuby 1.0 CTP for .NET 4.0 Beta2 (2009.10.21) DLR 0.92 (2009.10.22) Visual Studio 2010 ベータ2と合わせて試すのなら、IronRuby 1.0 CTP for .NET 4.0 Beta2 がお勧めです。その理由は、.NET Framework 4.0 ベータ2に同期した IronRuby と IronPython のバイナリが含まれているからです。 また、結構前からになります DLR を使った言語サンプルとして SymPL が以前に提供されていたToyLanguage に替わって提供されています。SymPLには、2種類の実装が提供されています。 charp:ExpandoObjectなどを使った言語実装です。 charp-cponly:DLR対応のホスティングサンプルです。 SymPLの実装方法自体は同じなのですが、ホスティング方法の違いで2種類が提供されています。DLR 対応として DLRホスティング可能なサンプルとしては、charp-cponlyをお勧めします。DLRホスティングの方法としては、以前に私が公開した…