好的。删除你所有的代码,重新开始。
如果你正在使用WPF,你需要摆脱所有过时的做法,理解并接受WPF思维。
在WPF中,你不会通过编程方式“选择一个TreeViewItem”,因为UI不是数据。
UI不负责跟踪你的数据项(显示在TreeView或任何其他UI元素中)的选中状态。
相反,你需要创建一个合适的DataModel和一个ViewModel
来分别保存数据和应用程序逻辑。
Josh Smith有一篇非常有趣的文章,解释了如何以正确的方式处理WPF中的TreeView。
基本上像这样:
<Window x:Class="MiscSamples.MVVMTreeViewSample"
xmlns="http:
xmlns:x="http:
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="">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="">
<CheckBox IsChecked="" Content=""/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</DockPanel>
</Window>
后台代码:
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>
{
}
}
}
数据项:
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));
}
}
结果:
![enter image description here](https://istack.dev59.com/i9KxJ.webp)
请看,没有任何代码操纵任何UI元素。一切都通过
DataBinding到
简单的属性和INotifyPropertyChanged来完成。这就是你在WPF中编程的方法。不需要复杂的
VisualTreeHelper.Whatever()
,也不需要复杂的操作,因为它们会导致各种问题,如UI虚拟化等。
在
SelectAll()
和
SelectNone()
方法中,我只是遍历
Data Items
而不是UI元素,并相应地设置它们的值。然后,WPF通过DataBinding引擎更新UI。
请看,没有必要将任何东西转换为任何东西,以及如何使用自己的简单类而不必处理复杂、晦涩的WPF对象模型。
忘掉winforms吧。它是个没用的恐龙,什么都不支持。
WPF非常棒。只需将我的代码复制并粘贴到
文件 -> 新建项目 -> WPF应用程序
中,亲自查看结果。请注意,您需要在
CreateData()
方法中添加项目到集合中。
如果您需要进一步的帮助,请告诉我。
ItemContainerStyle
来玩耍,但发现在TreeView
中不可能实现。然而,OP肯定需要多选功能,这可以通过将选择状态移动到Model/ViewModel来实现。请参见我的答案。 - Federico Berasategui