C#+WPFチューニング戦記

C#とWPFで高速なコードと最適なシステムを書くためにやってきたいろいろな事を書いてみます。.NET Frameworkのソースコードを読み解きましょう。なお、ここに書かれているのは個人の見解であって何らかの団体や企業の見解を代表するものではありません。

Canvas.LeftやCanvas.Topの動作について

パネルのうちで極めて自由度が高いといえばCanvasですが、使い込めば使い込むほど中身のことをしっかりと理解しておく必要を感じるはずです。

http://referencesource.microsoft.com/#PresentationFramework/src/Framework/System/Windows/Controls/Canvas.cs#223

http://referencesource.microsoft.com/#PresentationFramework/src/Framework/System/Windows/Controls/Canvas.cs#194

Canvas.Top/Leftはお馴染みですが、こんな風になってます。

  • コントロールはUIElementを継承していないと効果がありません。
  • VisualTreeHelperでの親がCanvasの場合だけ、InvalidateArrangeを実行します。

MSDNには特殊なシナリオでしか使わぬようにとあれだけはっきり書いてあった気がするのですが、InvalidateArrangeです。

FrameworkPropertyMetadataOption.AffectsParentArrangeではなくこちらを選択したのは、Canvas以外に対して無差別にInvalidateArrangeはしないようにするためだと考えられます。(他の理由もあるかもしれませんが。)

親の型に応じて処理を切り替える必要が多い添付プロパティにはこの種の処理が多いのです。つまり、パネルはMicrosoftにとっては特殊なシナリオなのだと言えるでしょう。

InvalidateArrangeは、Arrange処理中か、既にInvalidateArrangeしていなければ、ContextLayoutManagerのアレンジキューにUIElementを追加します。アレンジキュー自体は結構重い処理なので、これを多用しないようにというのはわからないでもありません。

しかし、1回アレンジキューに追加されれば、Arrange処理が走るまでは同じ処理は回避されます。すぐに処理から抜けるので、再描画が必要な状態においてInvalidateArrangeの利用自体を忌避する理由は実はそれほどありません。

InvalidateArrangeの観点からは、ボトルネックポイントになるのは、無駄に多くのUIElementをアレンジキューに追加してしまう事です。

 

つづく