WPF TreeView 想要在选择父级时选择第一个子级

发布于 2024-07-19 17:42:40 字数 883 浏览 7 评论 0原文

我正在使用演示模型通过 TreeView 控件在我的应用程序中实现导航。 我通过双向绑定将 TreeViewItem 的 IsSelected 属性绑定到我的视图模型。 当选择具有子节点的节点时,我希望选择该节点的第一个子节点而不是单击的节点。 在我的演示模型上设置 IsSelected 属性时,TreeViewItem 似乎没有侦听属性更改事件。 第一个子节点已被选中,但父节点并未取消选择。 这是我的演示模型中的代码。

public bool IsSelected {
    get {
        return this._isSelected;
    }
    set {
        if(this._isSelected != value) {
            this._isSelected = value;
            if(this.Nodes.Count > 0) {
                this._isSelected = false;
                this.Nodes[0].IsSelected = true;
            }
            this.NotifyPropertyChanged("IsSelected");
        }
    }
}

这是我的 TreeViewItem 的样式:

<Style TargetType="{x:Type TreeViewItem}">
    <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
</Style>

I am using a presentation model to implement navigation in my app with the TreeView control. I have the TreeViewItem's IsSelected property bound to my view model via two-way binding. When a node that has children is selected, I want the first child of that node to be selected instead of the one that is clicked. It seems like the TreeViewItem doesn't listen to the property changed event when it is setting the IsSelected property on my presentation model. The first child node is selected, but the parent node doesn't unselect. Here is the code from my presentation model.

public bool IsSelected {
    get {
        return this._isSelected;
    }
    set {
        if(this._isSelected != value) {
            this._isSelected = value;
            if(this.Nodes.Count > 0) {
                this._isSelected = false;
                this.Nodes[0].IsSelected = true;
            }
            this.NotifyPropertyChanged("IsSelected");
        }
    }
}

And here is the style for my TreeViewItem:

<Style TargetType="{x:Type TreeViewItem}">
    <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
</Style>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

要走就滚别墨迹 2024-07-26 17:42:40

我遇到了一个非常类似的问题,我发现当我通过代码选择一个子节点时,我还需要将焦点放在 TreeViewItem 包装器上,以便父节点将成为您所谓的“UnSelect”。 所以在 xaml 中我添加了一个事件处理程序:

<EventSetter Event="TreeViewItem.Selected" 
                    Handler="TreeViewItem_Selected" 
                        />

在部分类中:

Private Sub TreeViewItem_Selected(ByVal sender As System.Object, ByVal e As RoutedEventArgs)
            If CType(sender, TreeViewItem) IsNot Nothing Then
                CType(sender, TreeViewItem).Focus()
                e.Handled = True
            End If
End Sub

I had a very similar problem and i found out that when i select a child by code i need also to give focus to the TreeViewItem wrapper so the parent node will what you called "UnSelect". so in the xaml i added an event handler :

<EventSetter Event="TreeViewItem.Selected" 
                    Handler="TreeViewItem_Selected" 
                        />

And in the partial class :

Private Sub TreeViewItem_Selected(ByVal sender As System.Object, ByVal e As RoutedEventArgs)
            If CType(sender, TreeViewItem) IsNot Nothing Then
                CType(sender, TreeViewItem).Focus()
                e.Handled = True
            End If
End Sub
巷雨优美回忆 2024-07-26 17:42:40

需要考虑的另一种可能性:

TreeView 尝试确保不可能同时选择树中的两个 TreeViewItem,因此它应该防止这种情况发生。 也许这是 TreeView 中的一个错误,但也可能是您使用 TreeView 的方式有问题。

为了提高效率,TreeView 对于如何找到其下的 TreeViewItems 非常挑剔。 该算法实际上是这样的(以增量方式完成):

  1. 在我的项目容器中查找 TreeView 对象
  2. 在这些 TreeView 对象的项目容器中查找更多 TreeView 对象
  3. 重复步骤 3,直到找不到更多 TreeView 对象

因此,TreeView 只能查找如果 TreeViewItems 的每一层都直接位于前一层之下,则​​其后代。

例如,这可以工作:

<TreeView>
  <TreeViewItem>
    <TreeViewItem />
  </TreeViewItem>
  ...
</TreeView>

也可以这样:

<HierarchicalDataTemplate TargetType="{x:Type MyItemType"} ItemsSource="{Binding subItems}">
  ...
</HierarchicalDataTemplate>

<TreeView ItemsSource="{Binding items}" />

但如果插入非 TreeViewItems,则它将不起作用,如下所示:

<TreeView>
  <TreeViewItem>
    <Border>
      <TreeViewItem/>
    </Border>
  </TreeViewItem>
</TreeView>

或这样:

<TreeView>
  <DockPanel>
    <TreeViewItem>
      <TreeViewItem/>
    </TreeViewItem>
  </DockPanel>
</TreeView>

最后两种情况将显示得很好,但 TreeView 将看不到 TreeViewItems,因此它的选择代码将被禁用。 这会导致您所描述的症状。

我不知道你的情况是否属于这种情况,但我想我应该提一下以防万一。

Another possibility to consider:

TreeView attempts to make sure it is impossible for two TreeViewItems in the tree to be selected at once, so it should prevent this from happening. Perhaps it is a bug in TreeView, but it could also be a problem with the way you are using TreeView.

For efficiency's sake, TreeView is very picky about how it finds the TreeViewItems under it. The algorithm is effectively this (done in an incremental fashion):

  1. Look among my item containers for TreeView objects
  2. Look among those TreeView objects' item containers for more TreeView objects
  3. Repeat step 3 until no more TreeView objects found

Because of this, TreeView can only find its descendants if each level of TreeViewItems is directly under the previous one.

For example, this would work:

<TreeView>
  <TreeViewItem>
    <TreeViewItem />
  </TreeViewItem>
  ...
</TreeView>

and so would this:

<HierarchicalDataTemplate TargetType="{x:Type MyItemType"} ItemsSource="{Binding subItems}">
  ...
</HierarchicalDataTemplate>

<TreeView ItemsSource="{Binding items}" />

But it won't work if non-TreeViewItems are interposed, like this:

<TreeView>
  <TreeViewItem>
    <Border>
      <TreeViewItem/>
    </Border>
  </TreeViewItem>
</TreeView>

or this:

<TreeView>
  <DockPanel>
    <TreeViewItem>
      <TreeViewItem/>
    </TreeViewItem>
  </DockPanel>
</TreeView>

These last two cases will display just fine, but the TreeView will not see the TreeViewItems so its selection code will be disabled. This would cause the symptoms you describe.

I don't know whether this is the situation in your case or not, but I thought I should mention it just in case.

咽泪装欢 2024-07-26 17:42:40

这是 Amir 答案的 C# 版本:

 private void TreeViewItem_Selected(object sender, RoutedEventArgs e)
        {
            var treeViewItem = sender as TreeViewItem;
            if (treeViewItem != null)
            {
                treeViewItem.Focus();
                e.Handled = true;
            }
        }

This is C# version of Amir's answer:

 private void TreeViewItem_Selected(object sender, RoutedEventArgs e)
        {
            var treeViewItem = sender as TreeViewItem;
            if (treeViewItem != null)
            {
                treeViewItem.Focus();
                e.Handled = true;
            }
        }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文