1.はじめに
銀河の中昔は遠く 、遠く離れた.... マイクロソフトは、いくつかの検索VisualTreeの拡張メソッドを提供Silverlightのツールキット、中に便利なVisualTreeExtensionsを提供します。当時(2009年)で、私にとってVisualTreeExtensionsは、私はそれを自分で書いたので、私は感動した時のような万回以上のメソッドFindChildByNameを使用して簡単にちょうど良い例のコードのLINQと拡張メソッドです。そして、非常に実用的なので、私は(も、WPFで)このクラスを使用してきたが、今回は私がKino.Wpf.Toolkitに追加する必要があり、あなたにはでき、ここでソースコードを表示します。
2. VisualTreeExtensions機能
public static class VisualTreeExtensions
{
/// 获取 visual tree 上的祖先元素
public static IEnumerablelt;DependencyObjectgt; GetVisualAncestors(this DependencyObject element) { }
/// 获取 visual tree 上的祖先元素及自身
public static IEnumerablelt;DependencyObjectgt; GetVisualAncestorsAndSelf(this DependencyObject element) { }
/// 获取 visual tree 上的子元素
public static IEnumerablelt;DependencyObjectgt; GetVisualChildren(this DependencyObject element) { }
/// 获取 visual tree 上的子元素及自身
public static IEnumerablelt;DependencyObjectgt; GetVisualChildrenAndSelf(this DependencyObject element) { }
/// 获取 visual tree 上的后代元素
public static IEnumerablelt;DependencyObjectgt; GetVisualDescendants(this DependencyObject element) { }
/// 获取 visual tree 上的后代元素及自身
public static IEnumerablelt;DependencyObjectgt; GetVisualDescendantsAndSelf(this DependencyObject element) { }
/// 获取 visual tree 上的同级别的兄弟元素
public static IEnumerablelt;DependencyObjectgt; GetVisualSiblings(this DependencyObject element) { }
/// 获取 visual tree 上的同级别的兄弟元素及自身.
public static IEnumerablelt;DependencyObjectgt; GetVisualSiblingsAndSelf(this DependencyObject element) { }
}
VisualTreeExtensionsは、カプセル化VisualTreeHelper
し、問い合わせビジュアルツリーの様々な方法を提供し、私が使用し、日常、WPFに何ら問題はより機能的ではありません。そのような、実質的にコードの使用:
foreach (var item in this.GetVisualDescendants().OfTypelt;TextBlockgt;())
{
}
3.問題
使いやすいもののVisualTreeExtensions、まだ注意が必要いくつかの問題。
3.1 OnApplyTemplateを使用しないでください
FrameworkElementのは、現在のテンプレートと構成のビジュアルツリーOnApplyTemplateの関数呼び出しを生成するとき、それが最善である今回は、ビジュアルツリーの要素を取得するためにVisualTreeExtensionsを使用しません。いわゆる最高の WPF、Silverlightは、私はこの機能を実行するための経験に基づいて、短い時間で、はっきりと覚えていない瞬間が良いビジュアルツリー、VisualTreeHelperを構築しないかもしれないサブ要素を取得していない、いくつかの相違があったUWPのライフサイクルを制御しているため、 。どんなに私のメモリエラーならば、正しいアプローチが使用することですGetTemplateChildをするControlTemplate内の要素を取得します。
3.2深さ優先または幅優先
lt;StackPanel Margin=quot;8quot;gt;
lt;GroupBox Header=quot;GroupBoxquot; gt;
lt;TextBox Margin=quot;8quot; Text=quot;FirstTextBoxquot;/gt;
lt;/GroupBoxgt;
lt;TextBox Margin=quot;8quot;
Text=quot;SecondTextBoxquot; /gt;
lt;/StackPanelgt;
ページ上のような仮定は、以下のコードを実行します。
this.GetVisualDescendants().OfTypelt;Controlgt;().FirstOrDefault(c=gt;c.IsTabStop).Focus();
このコードは、キーボードフォーカス制御を受け入れ、それフォーカスすることができますこのページを見つけることが最初の意味します。直感的FirstTextBoxこのページの最初のフォーム項目は、それが焦点であるべきであるが、GetVisualDescendants
SecondTextBoxが集中しているように、幅優先探索方法は、FirstTextBoxよりSecondTextBoxの深い層です。
3.3ポップアップ問題
ポップアップ自分のビジュアルツリーを持って、それがビジュアルツリーに同じ児童ウィンドウでない時にポップアップを開きません。コンボボックスには、例えば、以下のコンボボックスのControlTemplate内の主要な構成です。
lt;Grid Name=quot;templateRootquot;
SnapsToDevicePixels=quot;Truequot;gt;
lt;Grid.ColumnDefinitionsgt;
lt;ColumnDefinition Width=quot;*quot; /gt;
lt;ColumnDefinition MinWidth=quot;{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}quot;
Width=quot;0quot; /gt;
lt;/Grid.ColumnDefinitionsgt;
lt;Popup Name=quot;PART_Popupquot;
AllowsTransparency=quot;Truequot;
Margin=quot;1quot;
Placement=quot;Bottomquot;
Grid.ColumnSpan=quot;2quot;
PopupAnimation=quot;{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}quot;
IsOpen=quot;{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}quot;gt;
lt;theme:SystemDropShadowChrome x:Name=quot;shadowquot;
Color=quot;Transparentquot;
MaxHeight=quot;{TemplateBinding ComboBox.MaxDropDownHeight}quot;
MinWidth=quot;{Binding ActualWidth, ElementName=templateRoot}quot;gt;
...
lt;/theme:SystemDropShadowChromegt;
lt;/Popupgt;
lt;ToggleButton Name=quot;toggleButtonquot;/gt;
lt;ContentPresenter Name=quot;contentPresenterquot;/gt;
lt;/Gridgt;
リアルタイムビジュアルツリービューで、2 VisualTree、およびポップアップがいなくてもそこにあります見ることができ、PopupRootと呼ばれる唯一のクラスがあります。具体的に参照し概説ポップアップこの文書では。
ComboBoxItemは、コンボボックスのVisualTreeの祖先は、ロジックツリーの検索に沿ったものであること取得したい場合でも、論理ツリー内のComboBoxポップアップは、そこにあります。
3.4ルート要素を探します
GetVisualAncestors
あなたは簡単にすべてのレベルでの祖先要素を見つけることができ、ルート要素は次のように使用することができます見つけるために、例えば、ルート要素を見つけることがされています:
element.GetVisualAncestors().Last()
要素がポップアップしていない場合でも、直接使用することを忘れないでくださいは、GetWindowを高速化:
Window.GetWindow(element)
5.その他のスキーム
多くのコントロールライブラリを使用すると、ここで、ツールのVisualTreeに探しているものをカプセル化したプログラムのコモンコントロールライブラリの一部は以下のとおりです。
- WindowsCommunityToolkit的VisualTree
- 拡張WPF Toolkitの的VisualTreeHelperEx
- MahApps.Metro的TreeHelper
- WPF(MUI)的のための近代的なUI VisualTreeHelperEx
- WinRTのXAMLツールキット的VisualTreeHelperExtensions
6.おわりに
VisualTreeExtensionsコードは非常に簡単です、私たちはUWP、UWPに使用することはできますが、習慣のうち、私はまだSilverlightのツールキットのバージョンを使用するだけであるため、新しいバージョンのWindowsCommunityToolkitを提供してきたと思います。そしてツールキットでFindDescendantByName(this DependencyObject element, string name)
、私が放棄されたときのことを思い出すFindChildByName
、エレガントではありません。
継続VisualTreeExtensions習慣は長年にわたって私が使用して書かれた拡張メソッド考える-Extensions
という名前のクラスサフィックスを、私はこの点で関連する規範を覚えていません。
7.参考
VisualTreeHelperクラス(System.Windows.Media)_マイクロソフトドキュメント
FrameworkElement.GetTemplateChild(String)メソッド(System.Windows)マイクロソフトのドキュメント