2016-08-18 41 views
0

因此,微软已决定通过程序化方式选择TreeView中的项目,因为某些疯狂的原因或其他原因而使得程序中的项目晦涩难懂并出现故障,并且是唯一的方法(因为虚拟化可确保您的任何TreeViewItem尝试选择当前不存在)是创建一个布尔IsVisible属性,无论你想用于你的源数据,它的方式必须实现INotifyPropertyChanged并包括一个事件处理程序现在,如果它没有之前,然后将一个ItemContainerStyle添加到您的TreeView中,将该属性绑定到TreeViewItem的IsVisible属性。TreeView项目选择与焦点不匹配

但是,不是但是,将焦点设置为所选项目,因此,例如,如果您的目标是让用户使用键盘删除树项目并让焦点自动移至已删除项目的父项目因此用户不必连续浏览项目或点击事物来获取他们的位置,这几乎是无用的。它以某种方式甚至不会避免虚拟化问题,允许您将选择设置为它在下一行代码中声明的内容不存在的内容。

这里是我的XAML:

和有关C#:

public partial class MainWindow : Window 
{ 
    public ObservableCollection<TreeEdit> Source { get; set; } 

    public MainWindow() 
    { 
     Source = new ObservableCollection<TreeEdit>(); 
     Source.Add(new TreeEdit("Hi")); 
     DataContext = this; 
     InitializeComponent(); 
    } 

    private void KeyNav(object sender, KeyEventArgs e) 
    { 
     TreeEdit Selection = (sender as TreeView).SelectedItem as TreeEdit; 
     ObservableCollection<TreeEdit> TSource = (ObservableCollection<TreeEdit>)(sender as TreeView).ItemsSource; 

     if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)) 
     { 
      if (e.Key == Key.Left && Selection != null) 
      { 
       if (Selection.Parent == null) 
       { 
        TSource.Remove(Selection); 
       } 
       else 
       { 
        Selection.Parent.IsSelected = true; 
        ((TreeViewItem)((sender as TreeView).ItemContainerGenerator.ContainerFromItem(Selection.Parent))).Focus(); 
        Selection.Parent.Remove(Selection); 
       } 
      } 
     } 
    } 
} 

public class TagEdit : INotifyPropertyChanged 
{ 
    public string Name 
    { 
     get 
     { 
      return name; 
     } 
     set 
     { 
      OnPropertyChanged("Name"); 
      name = value; 
     } 
    } 
    private string name; 
    public bool IsSelected 
    { 
     get 
     { 
      return selected; 
     } 
     set 
     { 
      OnPropertyChanged("IsSelected"); 
      selected = value; 
     } 
    } 
    private bool selected; 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected void OnPropertyChanged(string name) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(name)); 
     } 
    } 

    public TagEdit Parent; 
    public ObservableCollection<TagEdit> Children { get; set; } 

    public TagEdit(string n) 
    { 
     Name = n; 
     Children = new ObservableCollection<TagEdit>(); 
    } 

    public void Remove(TagEdit tag) 
    { 
     Children.Remove(tag); 
    } 
} 

这个想法是,用户可以通过箭头键正常浏览TreeView,然后使用Ctrl+Left删除选定的项目并选择其父项。 (sender as TreeView).ItemContainerGenerator.ContainerFromItem(Selection.Parent)通常返回null。删除它会导致选择适当的项目,但TreeView失去焦点。当它不返回null时,我得到预期的行为。

而且,尽管无论是TreeView的KeyboardNavigation.TabNavigationKeyboardNavigation.ControlTabNavigation被设置为Continue默认值,他们的行为不同(Tab忽略TreeView的构成要素而Ctrl+Tab步骤放进去)。

我一直在努力寻找一些东西,现在工作了将近一周的时间,如果我的开头段落没有提示你,我早已疲惫不堪。请不要告诉我尝试任何东西,除非您已经亲自输入了要告诉我尝试使用VisualStudio的工作。

道歉为苛刻的语调,但这个问题已经超出了荒谬的一段时间,并成为淫秽。

回答

0

WPF TreeView没有一个ItemContainerGenerator。树视图中的每个项目都是一个ItemsControl,因此它的子项目有其自己的ItemContainerGenerator。您真正需要做的是获取您要删除的项目的盛大父项,并使用该ItemContainerGenerator调用ContainerFromItem。

这不起作用,因为您正在尝试使用仅包含顶级项目的顶级ItemContainerGenerator。

P.S.在一个友好的一面说明:),谁删除项目与Ctrl +左?这是不可发现的。为什么不在删除时只做这种行为?