残念ながら、標準のWPF TreeViewコントロールには、読み取り専用のSelectedItemプロパティがあります。
したがって、 TreeViewに表示されるIsSelectedプロパティとIsExpandedプロパティを各オブジェクトに導入し、これらのプロパティを対応するTreeViewItemプロパティに関連付ける必要がありました。 ( 通常、これは彼らがインターネットでアドバイスすることです )
したがって、必要なオブジェクトにIsSelectedをインストールし、そのすべての祖先にIsExpandedをインストールするだけです。
この実装は正常に機能しますが、...
- ビジネスオブジェクトIsSelectedおよびIsExpandedを持つのはあまり良くありません。 また、ツリー内の各アイテムのビューモデルを作成するのは面倒です。
- ツリー検索は、コードに毎回実装する必要があります。これには、少なくとも時間がかかり、1つの単語で混乱が生じます。
一般的に、少し考えた後、そのような概念に来ました。
- ツリーノード内のオブジェクトの文字列表現の一部でオブジェクトを検索します。
- ロード時に、すべての親HierarchicalDataTemplateおよびDataTemplateを通過してオブジェクトの要素のすべてのバインディングを取得する必要があり、 HierarchicalDataTemplateには子へのパスがあります。
- アイテムソースの階層的なコレクションを検索する場合。 このデータを使用して、アイテムを検索します。
- 見つかったすべての要素は、ノードへのパスによって一緒に保存する必要があります。
- 見つかった要素の1つを選択する必要がある場合は、保存されたパスに沿って目的のノードを選択するだけです。
- オブジェクト( 双方向プロパティSelectedItemの実装)を選択するだけの場合、階層ItemSourceでそれを見つける必要があり、そのパスを覚えてから、パスに沿って目的のノードを選択します。
これは、すべてのテンプレートを検索する方法です。 ここではすべてが比較的簡単です。
public override void OnApplyTemplate() { base.OnApplyTemplate(); templateDescrColl = new TemplateDescriptionCollection();// List<FrameworkElement> parents= Helper.GetAllParent(this);// FindDataTemplatesResources(this.Resources);// foreach (FrameworkElement parent in parents) // { FindDataTemplatesResources(parent.Resources); } FindDataTemplatesResources(System.Windows.Application.Current.Resources);// }
テンプレートを検索するためのロジックは次のとおりです。検索パスを指定する別の方法があることを除いて、すべてが計画どおりです。
これは、バインダーの検索が常に機能するとは限らないため、一方で必要になる場合があります。
(別のコントロールを使用してノードを表示する場合、その複雑なロジックでは確実に機能しません)。
さて、一方で、検索のパスをより正確に示す必要がある場合があります。
パスは、文字列「TypeName1:Property1、Property2 TypeName2:」としてFindPatchesプロパティを介して設定されます。
この場合、TypeName1はProperties1、Property2によって検索され、TypeName2はまったく検索されません。
private void FindDataTemplatesResources(ResourceDictionary Resource) { foreach (object xxx in Resource.Values) { DataTemplate dataTemplate = xxx as DataTemplate; if (dataTemplate != null)// a DataTemplate { bool hierarhical=false; if (!templateDescrColl.ExistType(dataTemplate.DataType as Type, out hierarhical))// { TemplateBindingDescr templateBindingDescr = new TemplateBindingDescr();// HierarchicalDataTemplate hdt = xxx as HierarchicalDataTemplate;// HierarchicalDataTemplate here if (hdt != null) { Binding ItemsSourceBinding = hdt.ItemsSource as Binding; string ItemsSourcePath = ItemsSourceBinding.Path.Path; templateBindingDescr.itemSourcePath = ItemsSourcePath;// templateBindingDescr.IsHierathical = true; } Type tType = dataTemplate.DataType as Type; templateBindingDescr.TargetType = tType; // type if (! String.IsNullOrWhiteSpace (FindPatches) && FindPatches.Contains (tType.Name + ":")) // { Match match = Regex.Match (FindPatches, tType.Name + ":([^:]*)");. if (match.Success) { string re = match.Groups [1]. Value; string [] pathes = re.Split (','); templateBindingDescr.BindingPathes.AddRange (pathes); } } else // { FrameworkElement frameworkElement = dataTemplate.LoadContent () as FrameworkElement; // List <FrameworkElement> DependencyObjects = Helper.GetAllVisualChildren (frameworkElement);// if (DependencyObjects!= null) { foreach (FrameworkElement dependencyObject in DependencyObjects) { // BindingExpression BE = System.Windows.Data.BindingOperations.GetBindingExpression (dependencyObject, TextBlock.TextProperty); if (BE!= null) { string path = BE.ParentBinding.Path.Path; templateBindingDescr.BindingPathes.Add (path); } } } } templateDescrColl.Add (templateBindingDescr); // } } } }
これは、検索テキストを含むすべての要素の検索方法です。
/// <summary> /// FindText /// /// </summary> /// <param name="control"></param> /// <param name="FindText"></param> /// <returns></returns> public List<NamedObject> FindObjectByPropertyNames(IEnumerable itemsSource, List<int> path) { List<NamedObject> ret = new List<NamedObject>();// int i = 0; path.Add(i);// foreach (object Item in itemsSource) // { path[path.Count - 1] = i;// TemplateBindingDescr desctiption= templateDescrColl.Get(Item.GetType());// string subItemsPath=desctiption.itemSourcePath;// string ObjectText=String.Empty;// bool ok=false; foreach (string findPath in desctiption.BindingPathes)// { object ItemVal = Item.GetObjectSubItem(findPath); // if (ItemVal != null )// { string ItemText = ItemVal.ToString().ToUpper();// ObjectText += ItemText + " "; if (ItemText.Contains(FindText.ToUpper())) { ok = true; // } } } if (ok)// { List<int> path2 = new List<int>(); path2.AddRange(path); ret.Add(new NamedObject() { Name = ObjectText, Item = Item, Path = path2 });// } if (subItemsPath != null)// { IEnumerable subItems=Item.GetObjectSubItem(subItemsPath) as IEnumerable; if (subItems != null) { List<int> path1 = new List<int>(); path1.AddRange(path); ret.AddRange(FindObjectByPropertyNames(subItems, path1)); } } i++; } return ret; }
これは、検索テキストを含むすべての要素の検索方法です。
int failCount; // // void SelectNodeByPath(ItemsControl control, IEnumerable<int> path) { List<int>L= path.ToList<int>(); if (L.Count == 0) { return; } if (control.Items.Count > L[0]) { do // { control.UpdateLayout(); } while (control.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated); TreeViewItem dObject = control.ItemContainerGenerator.ContainerFromIndex(L[0]) as TreeViewItem; if (dObject == null)// { dObject = GetTreeViewItem(control, L [0]); } if (dObject == null) { MessageBox.Show(" ); } else // { L.RemoveAt(0); if (L.Count == 0) // { dObject.IsSelected = true; dObject.BringIntoView(); } else // { dObject.IsExpanded = true; SelectNodeByPath(dObject, L); // } } } else { MessageBox.Show(" "+control.Items.Count+" > "+L[0]); } }
GetTreeViewItem関数(コントロール、L [0]); 信頼できる結び目を確実に見つけることができます
大変混乱しています。 指定されたサイトのコードに基づきます。
blogs.msdn.com/b/wpfsdk/archive/2010/02/23/finding-an-object-treeviewitem.aspx
これが新しいコードです。
myTreeViewWith search.zip
検索は別のスレッドで機能します。
ユーザーが検索するプロパティを選択できるように、高度な検索を行うことができます
そして...しかし、これは装飾であり、アイデアは機能します。
PS投稿の著者である私の兄弟SergejSh-それに関するすべての質問とコメント。