好的。刪除所有的代碼並從頭開始。
如果你正在使用WPF,你真的需要拋棄恐龍技術(如winforms)的所有古老做法,並理解並接受The WPF Mentality。
在WPF中,您沒有「編程選擇TreeViewItem」,只是因爲UI is Not Data。
UI不負責跟蹤您的數據項的選擇狀態,這些數據項顯示在TreeView或任何其他UI元素中。
相反,您將分別創建適當的DataModel和ViewModel
來保存數據和應用程序邏輯。
有一個非常有趣的article作者Josh Smith解釋瞭如何處理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到簡單,簡單的屬性和INotifyPropertyChanged。這就是你在WPF中編程的方式。不需要複雜的東西,不需要由於UI虛擬化等引起的各種問題的複雜操作。
- 在
SelectAll()
和SelectNone()
方法中,我只是遍歷Data Items
而不是UI元素,並相應地設置它們的值。 WPF然後通過DataBinding引擎更新UI。
- 瞭解如何不需要向任何東西施加任何東西,以及如何使用我自己的簡單類而不是處理複雜的,神祕的WPF對象模型。
- 忘記winforms。這是一個無用的恐龍,不支持任何東西。
- WPF Rocks。只需將我的代碼複製並粘貼到
File -> New Project -> WPF Application
中即可自行查看結果。請注意,您需要在CreateData()
方法中將項目添加到集合中。
- 讓我知道你是否需要進一步的幫助。
我也想指出,除非你做了一些特別的事情,TreeView只允許選擇一個項目。 –
@JoelLucsy沒錯。我試着去玩'ItemContainerStyle'只是爲了找出它不可能用'TreeView'。然而,OP肯定需要多次選擇,這可以通過將選擇狀態移動到Model/ViewModel來實現。看到我的答案。 –