TreeView项目选择与焦点不匹配

时间:2016-08-18 17:42:51

标签: c# wpf treeview

因此,微软已经决定以编程方式选择TreeView中的项目,因为某些疯狂的原因或其他原因而难以实现并且出现故障,这是实现这一目标的唯一方法(因为虚拟化确保您尝试选择的任何TreeViewItem都不会出现这种情况。 ; t当前存在)是在你想要用于源数据的任何东西上创建一个布尔的IsVisible属性,顺便说一下,它必须实现INotifyPropertyChanged并且如果它之前没有包含事件处理程序,然后添加一个TreeView的ItemContainerStyle将属性绑定到TreeViewItem的IsVisible属性。

的内容是将焦点设置为所选项目,因此,例如,如果您的目标是让用户使用键盘删除树项目并自动获得焦点转移到已删除项目的父级,以便用户不必连续浏览项目或点击某些内容以获取其位置,这几乎是无用的。它在某种程度上甚至无法避免虚拟化问题,允许您将选择设置为它在下一行代码中所声称的内容并不存在。

这是我的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&# 39; s Ctrl+Tab进入它们时的组成元素。)

我一直试图获得一些东西,任何东西都可以工作近一个星期,如果我的开头段落没有让你失望,我已经厌倦了我的耐心。请不要告诉我尝试任何事情,除非你已经做过,亲自输入你要告诉我尝试进入VisualStudio的内容并且它有效。

对于严厉的语气道歉,但这个问题在一段时间之前已经超出了荒谬和淫秽。

1 个答案:

答案 0 :(得分:0)

WPF TreeView没有单个ItemContainerGenerator。树视图中的每个项都是ItemsControl,因此其子项具有自己的ItemContainerGenerator。你真正需要做的是获得你要删除的项目的祖父项,并使用THAT ItemContainerGenerator来调用ContainerFromItem。

它无法正常工作,因为您正在尝试使用仅包含顶级项目的顶级ItemContainerGenerator。

P.S。在一个友好的方面注意:),谁用Ctrl + Left删除项目?这是不可能发现的。为什么不在他们点击删除时执行此操作?