我正在尝试创建一个递归方法来取消选择WPF TreeView中的所有项目.使事情变得复杂的是每个TreeViewItem都不是迷你TreeView.这会导致你不得不来回做很多.所以,这是我尝试过的:
TreeViewDeselectAll(myTreeView.Items);
// Must send in ItemCollection to allow the recursive call
private void TreeViewDeselectAll(ItemCollection myTreeViewItems)
{
// The only way to get to the IsSelected property is to turn it back into a TreeViewItem
foreach (TreeViewItem currentItem in myTreeViewItems)
{
currentItem.IsSelected = false;
if (currentItem.HasItems)
{
// Recursify!
TreeViewDeselectAll(currentItem.Items);
}
}
}
Run Code Online (Sandbox Code Playgroud)
有没有人成功取消选择TreeView中的所有项目?您是否能够以递归方式遍历TreeView?
Winforms TreeView有一个Nodes集合,它实际上是一个迷你TreeView.这允许递归很好.但是WPF TreeView没有节点.
在.Net 4.0中工作.
好.删除所有代码并从头开始.
如果你正在使用WPF,你真的需要留下恐龙技术(如winforms)的所有古老实践,并理解和拥抱WPF心态.
在WPF中,您不是以编程方式"选择TreeViewItem",因为UI不是数据.
UI不负责跟踪数据项的选择状态,这些状态显示在TreeView或任何其他UI元素中.
相反,您可以分别创建适当的DataModel和a ViewModel来保存数据和应用程序逻辑.
有一个很有趣的文章由约什-史密斯解释如何处理在WPF,以正确的方式一个TreeView.
基本上是这样的:
<Window x:Class="MiscSamples.MVVMTreeViewSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MVVMTreeViewSample" Height="300" Width="300">
<DockPanel>
<Button Content="Select All" Click="SelectAll" DockPanel.Dock="Top"/>
<Button Content="Select None" Click="SelectNone" DockPanel.Dock="Top"/>
<TreeView ItemsSource="{Binding}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<CheckBox IsChecked="{Binding IsSelected}" Content="{Binding DisplayName}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</DockPanel>
</Window>
Run Code Online (Sandbox Code Playgroud)
代码背后:
public partial class MVVMTreeViewSample : Window
{
private ObservableCollection<HierarchicalData> Data;
public MVVMTreeViewSample()
{
InitializeComponent();
DataContext = Data = CreateData();
}
private void Select(IEnumerable<HierarchicalData> items, bool isselected)
{
while (items.Any())
{
items.ToList().ForEach(x => x.IsSelected = isselected);
items = items.SelectMany(x => x.Children);
}
}
private void SelectAll(object sender, RoutedEventArgs e)
{
Select(Data, true);
}
private void SelectNone(object sender, RoutedEventArgs e)
{
Select(Data, false);
}
private ObservableCollection<HierarchicalData> CreateData()
{
return new ObservableCollection<HierarchicalData>
{
//... Dummy Data here
}
}
}
Run Code Online (Sandbox Code Playgroud)
数据项:
public class HierarchicalData : System.ComponentModel.INotifyPropertyChanged
{
public string DisplayName { get; set; }
private bool _isSelected;
public bool IsSelected
{
get { return _isSelected; }
set
{
_isSelected = value;
OnPropertyChanged("IsSelected");
}
}
public ObservableCollection<HierarchicalData> Children { get; private set; }
public HierarchicalData()
{
Children = new ObservableCollection<HierarchicalData>();
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
Run Code Online (Sandbox Code Playgroud)
结果:

VisualTreeHelper.Whatever()东西,不需要由于UI虚拟化等引起各种问题的复杂操作.SelectAll()和SelectNone()方法中,我只是迭代Data Items而不是UI元素,并相应地设置它们的值.然后,WPF通过DataBinding引擎更新UI.File -> New Project -> WPF Application然后自己查看结果.请注意,您需要在CreateData()方法中向项目集添加项目.