好的。删除所有代码并重新开始。
如果您正在使用 WPF,那么您确实需要抛弃所有来自恐龙技术(如 winform)的过时做法,并理解并接受 The WPF Mentality。
在 WPF 中,您不会以编程方式“选择 TreeViewItem”,这仅仅是因为 UI is Not Data。
UI 不负责跟踪数据项的选择状态,这些数据项显示在 TreeView 或任何其他 UI 元素中。
相反,您创建一个适当的 DataModel 和一个 ViewModel 来分别保存数据和应用程序逻辑。
Josh Smith 有一个非常有趣的article 解释了如何在 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>
代码背后:
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
}
}
}
数据项:
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));
}
}
结果:
- 看看如何没有一行代码可以操作任何 UI 元素。一切都通过DataBinding 完成Simple、Simple Properties 和 INotifyPropertyChanged。这就是您在 WPF 中编程的方式。不需要复杂的
VisualTreeHelper.Whatever() 东西,不需要由于 UI 虚拟化等导致各种问题的复杂操作。
- 在
SelectAll() 和SelectNone() 方法中,我只是通过Data Items 而不是UI 元素进行迭代,并相应地设置它们的值。然后 WPF 通过 DataBinding 引擎更新 UI。
- 了解如何无需将任何内容强制转换为任何内容,以及我如何使用自己的简单类而不是处理复杂、神秘的 WPF 对象模型。
- 忘记winforms。它是一个无用的恐龙,什么都不支持。
-
WPF 摇滚。只需将我的代码复制并粘贴到
File -> New Project -> WPF Application 中,然后自己查看结果。请注意,您需要在 CreateData() 方法中将项目添加到集合中。
- 如果您需要进一步的帮助,请告诉我。