TreeView
中选择项目?ItemsControl
模型似乎会阻止此操作。TreeView
中选择项目?ItemsControl
模型似乎会阻止此操作。对于那些仍在寻找解决此问题的正确方法的人,以下是一个可行方案。我在“WPF TreeView Selection”文章(http://www.codeproject.com/KB/WPF/TreeView_SelectionWPF.aspx)的评论中找到了这个方案,作者是DaWanderer。该方案由Kenrae于2008年11月25日发布,对我非常有效。谢谢Kenrae!
不要遍历整个树,而是让您自己的数据对象具有“IsSelected”属性(我建议也要有“IsExpanded”属性)。使用TreeView的ItemContainerStyle属性为树的TreeViewItems定义样式,将这些属性从TreeViewItem绑定到您的数据对象。类似这样:
<Style x:Key="LibraryTreeViewItemStyle"
TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded"
Value="{Binding IsExpanded, Mode=TwoWay}" />
<Setter Property="IsSelected"
Value="{Binding IsSelected, Mode=TwoWay}" />
<Setter Property="FontWeight"
Value="Normal" />
<Style.Triggers>
<Trigger Property="IsSelected"
Value="True">
<Setter Property="FontWeight"
Value="Bold" />
</Trigger>
</Style.Triggers>
</Style>
<TreeView ItemsSource="{Binding Path=YourCollection}"
ItemContainerStyle="{StaticResource LibraryTreeViewItemStyle}"
ItemTemplate={StaticResource YourHierarchicalDataTemplate}/>
因为某种奇怪的原因,这真是一件令人头痛的事情,你必须使用ContainerFromItem来获取容器,然后调用select方法。
// selectedItemObject is not a TreeViewItem, but an item from the collection that
// populated the TreeView.
var tvi = treeView.ItemContainerGenerator.ContainerFromItem(selectedItemObject)
as TreeViewItem;
if (tvi != null)
{
tvi.IsSelected = true;
}
以前有一篇博客文章介绍如何做这个,在这里,但是链接现在已经失效了。
TreeViewItem
并将 IsSelected
设置为 true
。我已经成功运行了这段代码:
public static TreeViewItem FindTviFromObjectRecursive(ItemsControl ic, object o) {
//Search for the object model in first level children (recursively)
TreeViewItem tvi = ic.ItemContainerGenerator.ContainerFromItem(o) as TreeViewItem;
if (tvi != null) return tvi;
//Loop through user object models
foreach (object i in ic.Items) {
//Get the TreeViewItem associated with the iterated object model
TreeViewItem tvi2 = ic.ItemContainerGenerator.ContainerFromItem(i) as TreeViewItem;
tvi = FindTviFromObjectRecursive(tvi2, o);
if (tvi != null) return tvi;
}
return null;
}
使用方法:
var tvi = FindTviFromObjectRecursive(TheTreeView, TheModel);
if (tvi != null) tvi.IsSelected = true;
如何展开TreeView中的项?-第三部分: http://bea.stollnitz.com/blog/?p=59
在TreeView中以编程方式选择项: http://blog.quantumbitdesigns.com/2008/07/22/programmatically-selecting-an-item-in-a-treeview/#respond
TreeView、TreeViewItem和IsSelected: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/7e368b93-f509-4cd6-88e7-561e8d3246ae/
我写了一个扩展方法:
using System.Windows.Controls;
namespace Extensions
{
public static class TreeViewEx
{
/// <summary>
/// Select specified item in a TreeView
/// </summary>
public static void SelectItem(this TreeView treeView, object item)
{
var tvItem = treeView.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;
if (tvItem != null)
{
tvItem.IsSelected = true;
}
}
}
}
我可以像这样使用它:
if (_items.Count > 0)
_treeView.SelectItem(_items[0]);
if (TreeView1.Items.Count > 0)
(TreeView1.Items[0] as TreeViewItem).IsSelected = true;
private static void DeselectTreeViewItem(IEnumerable<TreeViewItem> treeViewItems)
{
foreach (var treeViewItem in treeViewItems)
{
if (treeViewItem.IsSelected)
{
treeViewItem.IsSelected = false;
return;
}
DeselectTreeViewItem(treeViewItem.Items.Cast<TreeViewItem>());
}
}
使用方法:
private void ClearSelectedItem()
{
if (AssetTreeView.SelectedItem != null)
{
DeselectTreeViewItem(AssetTreeView.Items.Cast<TreeViewItem>());
}
}
public bool Select(TreeViewItem item, object select) // recursive function to set item selection in treeview
{
if (item == null)
return false;
TreeViewItem child = item.ItemContainerGenerator.ContainerFromItem(select) as TreeViewItem;
if (child != null)
{
child.IsSelected = true;
return true;
}
foreach (object c in item.Items)
{
bool result = Select(item.ItemContainerGenerator.ContainerFromItem(c) as TreeViewItem, select);
if (result == true)
return true;
}
return false;
}
VisualTreeExt.GetDescendants<T>
,它返回一个可枚举的元素集合,这些元素与指定类型匹配:public static class VisualTreeExt
{
public static IEnumerable<T> GetDescendants<T>(DependencyObject parent) where T : DependencyObject
{
var count = VisualTreeHelper.GetChildrenCount(parent);
for (var i = 0; i < count; ++i)
{
// Obtain the child
var child = VisualTreeHelper.GetChild(parent, i);
if (child is T)
yield return (T)child;
// Return all the descendant children
foreach (var subItem in GetDescendants<T>(child))
yield return subItem;
}
}
}
VisualTreeHelperExt.GetDescendants<TreeViewItem>(MyAmazingTreeView)
时,你将获得所有的 TreeViewItem
子项。你可以使用下面的代码选择特定的值:var treeViewItem = VisualTreeExt.GetDescendants<TreeViewItem>(MyTreeView).FirstOrDefault(tvi => tvi.DataContext == newValue);
if (treeViewItem != null)
treeViewItem.IsSelected = true;
这个方法有点“脏”(可能不是最有效的),如果您使用虚拟化TreeView,则无法使用它,因为它依赖于实际可视元素的存在。但对于我的情况有效...