2

I have a TreeView control with 2-level hierarchy. If an item of the second level is selected and a user clicks on another item, I need to ask him whether he is sure to move to another item. If his answer is 'no', I need to prevent another TreeViewItem from selection.

I try this way:

<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;
            }
        }
    }
}

In a way that works. However, the problem is that I get OnMouseDown event twice: for the first-level item and for the second level item. For example, for this tree: Russia - Moscow - Piter USA - New-York - Boston If I click Boston, I get first event for the USA and then for Boston. So, I can't distinguish the cases:

  1. when user clicks on USA
  2. when user click on Boston and I just get the first part of tunneling event

In TreeViewItem_OnMouseDown I need to know the TreeViewItem which user clicked on.

Could you advice me, how I can determine the TreeViewItem which user clicked on in TreeViewItem_OnMouseDown? Again, if I just check a sender. It maybe USA, but actually user clicked on Boston. So I need to realize that it was Boston.

4

1 回答 1

1

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

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:取消数据绑定列表框中的用户选择?

于 2013-09-02T21:20:51.123 回答