树视图项目选择vs焦点不匹配

本文关键字:焦点 不匹配 vs 选择 视图 项目 | 更新日期: 2023-09-27 18:03:04

所以微软已经决定使程序选择项目的过程在一个树视图极其困难和故障的一些疯狂的原因或其他,和唯一的方法做到这一点(因为虚拟化确保任何TreeViewItem你试图选择不存在)是创建一个布尔IsVisible属性,无论你想使用你的源数据。顺便说一下,它必须实现INotifyPropertyChanged,并包括一个事件处理程序现在,如果它以前没有,然后添加一个ItemContainerStyle到你的TreeView绑定属性到TreeViewItem的IsVisible属性。

然而,没有做的是将焦点设置为所选项目,因此,如果您的目标是让用户使用键盘删除树项目,并将焦点自动转移到已删除项目的父项,这样用户就不必连续地通过项目tab或单击事物以恢复其位置,这几乎是无用的。它甚至不能避免虚拟化问题,允许您将选择设置为它在下一行代码中声明的不存在的东西。 下面是我的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中并且它有效。

很抱歉我的语气很刺耳,但这个问题在一段时间前就已经超出了荒谬的范畴,变成了淫秽。

树视图项目选择vs焦点不匹配

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

它不工作,因为你试图使用顶级ItemContainerGenerator,它只包含顶级项目。

注:说句友好的话:),谁会用Ctrl+Left来删除项目呢?原先的。为什么不在他们点击Delete时做这个行为呢?