c# - 如何防止 TreeViewItem 选择?

标签 c# .net wpf treeview treeviewitem

我有一个具有 2 级层次结构的 TreeView 控件。 如果选择了第二层的一个项目,用户点击了另一个项目,我需要问他是否确定要移动到另一个项目。如果他的回答是“否”,我需要阻止选择另一个 TreeViewItem。

我这样试试:

<TreeView.Resources>
    <Style TargetType="{x:Type TreeViewItem}">
        <EventSetter Event="PreviewKeyDown" Handler="TreeViewItem_OnKeyDown" />
    </Style>
</TreeView.Resources>


private void TreeViewItem_OnMouseDown(object sender, MouseButtonEventArgs e)
{
    var selectedTreeViewItem = sender as TreeViewItem;
    if (selectedTreeViewItem != null)
    {
        var myData = selectedTreeViewItem.Header as MyData;
        if (myData != null && selectedNode != null)
        {
            if (!selectedNode.DoYouAgreeToMoveToAnotherItem())
            {
                e.Handled = true;
            }
            else
            {
                myTreeView.Focus();
                myData.IsNodeSelected = true;
            }
        }
    }
}

以一种行之有效的方式。但是,问题是我两次收到 OnMouseDown 事件:第一级项目和第二级项目。 例如,对于这棵树: 俄罗斯 - 莫斯科 - 彼得 美国 - 纽约 - 波士顿 如果我单击波士顿,我将获得美国的第一个事件,然后是波士顿的事件。所以,我无法区分大小写:

  1. 当用户点击美国时
  2. 当用户点击 Boston 时,我得到了隧道事件的第一部分

在 TreeViewItem_OnMouseDown 中,我需要知道用户点击了哪个 TreeViewItem。

你能告诉我,我如何确定用户在 TreeViewItem_OnMouseDown 中点击的 TreeViewItem 吗?同样,如果我只是检查发件人。它可能是美国,但实际上用户点击了波士顿。所以我需要意识到那是波士顿。

最佳答案

好吧,这只是一个粗略的示例,但您可以从后面的代码中像这样处理它。

XAML

<TreeView ...>
    <TreeView.Resources>
        <Style TargetType="{x:Type TreeViewItem}">
            <EventSetter Event="PreviewMouseLeftButtonDown" Handler="treeViewItem_PreviewMouseLeftButtonDown" />
        </Style>
    </TreeView.Resources>
    ...
</TreeView>

一些辅助方法

public static T GetFirstAncestorOfType<T>(DependencyObject source) where T : class
{
    while (source != null && !(source is T))
        source = VisualTreeHelper.GetParent(source);
    return source as T;
}

public static MessageBoxResult DoYouAgreeToMoveToAnotherItem()
{
    return MessageBox.Show("Select a different item?", "Select?", MessageBoxButton.YesNo);
}

代码隐藏

private TreeViewItem _selectedItem = null;

void treeViewItem_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    TreeViewItem tvi = GetFirstAncestorOfType<TreeViewItem>(e.OriginalSource as DependencyObject);

    if (_selectedItem != null &&
        tvi != null &&
        tvi != _selectedItem &&
        MessageBoxResult.Yes != DoYouAgreeToMoveToAnotherItem())
    {
        e.Handled = true;
    }
    else
    {
        // Update _selectedItem for comparison the next time this method fires.
        _selectedItem = tvi;
        if(_selectedItem != null)
            _selectedItem.IsSelected = true;
    }
}

您也可以使用纯 MVVM 来完成此操作.我没有时间发布使用 TreeView 的示例,但解决方案可能涉及使用 Dispatcher,类似于此处提供的解决方案...

WPF: Cancel a user selection in a databound ListBox?

关于c# - 如何防止 TreeViewItem 选择?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18577565/

相关文章:

c# - 编译查询没有隐式引用转换为 ObjectContext

c# - 比较大文本文件 - 比较散列是否比使用文件的子集更快?

c# - 在代码隐藏中添加网格

c# - MVVM 按钮内容属性不起作用

javascript - 如何在 C#/asp.Net/Razor 中异步获取用户键盘输入

c# - 俄罗斯增值税号验证

c# - 使用LINQ to SQL根据内存列表生成SQL

c# - ASP.NET 的编译文件目录

c# - 如何跨类使用TraceSource

c# - 在 WPF MVVM 中处理模型中的集合