当前位置: 首页 > 知识库问答 >
问题:

WPF在树视图中操作选定的项目

杜高谊
2023-03-14

我有一个树状视图,其中有可选择的项,以及可能触发某些代码操作的子项。单击子项时,应执行操作,但父项必须保留/成为选定项。

我面临的问题是项目没有被正确取消选择,导致在树视图中选择多个项目。

以下是treeview的xaml:

    <TreeView Name="Treeview1" Style="{StaticResource vcc_Treeview}" >
        <TreeView.ItemTemplate >
            <HierarchicalDataTemplate ItemsSource="{Binding Children}" >
                <StackPanel Orientation="Horizontal">
                    <Image Source="{Binding ImgSrc}" Style="{StaticResource vcc_TreeviewItemImage}" />
                    <TextBlock Text="{Binding Description}" Style="{StaticResource vcc_TreeviewItemTextblock}" Foreground="{Binding TextColorBrush}" />
                </StackPanel>
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
        <TreeView.ItemContainerStyle>
            <Style TargetType="TreeViewItem">
                <Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay, Converter={StaticResource clsBindingDebugger}}" />
            </Style>
        </TreeView.ItemContainerStyle>
    </TreeView>

clsBindingDebugger除了调试打印转换的值并传递转换和转换回值之外什么也不做。

接下来是TreeviewItem类的略为缩短的版本

Public Class MyTreeviewItem
Implements INotifyPropertyChanged

Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

Public Event MyTreeviewItem_ExpandedChanged(MTI As MyTreeviewItem, IsExpanded As Boolean)
Public Event MyTreeviewItem_SelectedChanged(MTI As MyTreeviewItem, IsSelected As Boolean)



Public Sub New(Optional Level_ As Integer = 1, Optional ByVal Key_ As String = "")
    MyBase.New()
    Me.Children = New ObservableCollection(Of MyTreeviewItem)
    _Key = Key_
    _Level = Level_
End Sub

Private _Level As Integer
Public Property Level As Integer
    Get
        Level = _Level
    End Get
    Set(value As Integer)
        _Level = value
    End Set
End Property

Private _Descr As String = ""
Public Property Description As String
    Get
        Description = _Descr
    End Get
    Set(value As String)
        _Descr = value
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Description"))
    End Set
End Property

Private _Key As String = ""
Public Property Key As String
    Get
        Key = _Key
    End Get
    Set(value As String)
        _Key = value
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Key"))
    End Set
End Property

Private _ImgSrc As ImageSource
Public Property ImgSrc As ImageSource
    Get
        ImgSrc = _ImgSrc
    End Get
    Set(value As ImageSource)
        _ImgSrc = value
    End Set
End Property

Private _Children As ObservableCollection(Of MyTreeviewItem)
Public Property Children As ObservableCollection(Of MyTreeviewItem)
    Get
        Return _Children
    End Get
    Set(value As ObservableCollection(Of MyTreeviewItem))
        _Children = value
    End Set
End Property

Private _IsSelected As Boolean
Overloads Property IsSelected As Boolean
    Get
        Return _IsSelected
    End Get
    Set(ByVal value As Boolean)
        _IsSelected = value
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("IsSelected"))
        RaiseEvent MyTreeviewItem_SelectedChanged(Me, _IsSelected)
    End Set
End Property

Private _IsActionItem As Boolean
Overloads Property IsActionItem As Boolean
    Get
        Return _IsActionItem
    End Get
    Set(ByVal value As Boolean)
        _IsActionItem = value
    End Set
End Property
End Class

最后我触发事件MyTreeviewItem_SelectedChanged:

Private ReselectingParent As Boolean = False

Private Sub MyTreeviewItem_SelectedChanged(MTI As MyTreeviewItem, IsSelected As Boolean)
Debug.Print(MTI.Description & "  Selected = " & IsSelected)
If ReselectingParent Then Exit Sub

If IsSelected Then

    'Do some (action) stuff here

    If MTI.IsActionItem AndAlso MTI.Parent IsNot Nothing Then
        ReselectingParent = True 'to prevent this sub from being executed with the next 2 lines
        MTI.IsSelected = False
        MTI.Parent.IsSelected = True
        ReselectingParent = False
    End If
End If
End Sub

假设树视图看起来像:

item 1
--Action 1
--Action 2
Item 2
--Action 3
--Action 4

在我开始的情况下,项目2被选中。现在我单击操作1,所以操作应该被执行,之后的项目1应该是所选的项目。debug.print结果如下:

ConvertBack: False
Item 2  Selected = False
Convert: False
ConvertBack: True
Action 2  Selected = True
Action 2  Selected = False
Convert: True
Item 1  Selected = True
Convert: False

此时,项目1被选中,这是应该的。现在我点击动作3。

ConvertBack: False
Action 2  Selected = False
Convert: False
ConvertBack: True
Action 3  Selected = True
Action 3  Selected = False
Convert: True
Item 2  Selected = True
Convert: False

结果是项目1和项目2都被选中,其中只应选择项目2。第二个调试器块显示“Action 2 Selected=False”,这应该是“Item 1 Selected=False”

我希望我说清楚了。谁能告诉我问题的解决方法?谢谢!

共有1个答案

田博易
2023-03-14

对谁感兴趣。。。

我仍然不太明白为什么代码不能正常工作。但显然,单击的操作项没有被正确取消选择。不要打这些电话:

    ReselectingParent = True 'to prevent this sub from being executed with the next 2 lines
    MTI.IsSelected = False
    MTI.Parent.IsSelected = True
    ReselectingParent = False

直接在MyTreeviewItem\u Selected Changed中,我现在改为调用计时器。在timer_appeased事件中,我调用四行。显然,在调用代码选择其父项时,操作项的主选择尚未完成。这是一个丑陋的解决办法,但对我来说很有效。。。

 类似资料:
  • 我正在实现一个类别映射器。有2树视图。两者都包含来自不同来源的类别。(即使他们看起来像来自同一个来源) 用户应该能够将一个类别从左侧映射到右侧树状视图的多个。它存储在配置文件中。 但是,当视图最初加载并且用户单击左侧的类别时,我想预选右侧的映射类别,从配置文件加载。 我看到我可以用一个选项来做这件事,但是我没有看到一个选项可以用多个选项来做这件事。 我怎样才能做到这一点? 这里有一个ootb正在运

  • 我有一个绑定到MVVM可观察集合的TreeView。我的项目模板由图像和文本块组成,如以下代码所示: 当然,发生这种情况是因为堆栈面板现在位于选择区域上方。 有什么解决办法吗?

  • 新加入WPF的我正尝试使用TreeView,它提供的灵活性给我留下了难以置信的印象。 到目前为止,我的每个treeview项目都实现了一个扩展器,这是显示每个项目更详细信息并让标题仅显示摘要的好方法。但是,这不适合叶项目,并且浪费了屏幕空间——我的treeview中的每个叶项目(其中有许多)显示的数据量相对较小。 我想要为叶项目实现的是水平包装,而不是垂直列表。设想显示一个网格或(stackpan

  • 我工作在一个WPF应用程序,我有2树视图。两者都有一个ViewModel对象集合作为其ItemsSource。我试图使它,当用户选择一个TreeView中的项目时,其他的选择被更改为空。 但是,我注意到TreeView中的实际项目属于SomethingViewModel类型,而不是TreeView项目。这意味着他们没有选择的财产。我已经尝试将IsSelected属性添加到ViewModel对象,并

  • 我有一个WPF TreeView,希望在所有没有子项的TreeView项目上侦听双击。我的树视图如下所示: 树状视图的内容是这样生成的: 在我的XAML文件中,我定义了一个EventSetter,单击TreeViewItem时应该触发它: 在我的代码隐藏中,我定义了处理程序: 当我双击任何TreeViewItem时,处理程序被触发,但每次发送者都是TreeViewItem“级别1”。我想得到点击的

  • 我正在学习WPF,我想我缺少一些用户控件。我将尝试用例子来演示。基本上,假设我有一个treeview,我想将标签文本绑定到treeview selectedItem。这似乎很简单: 现在,为了使事情复杂化,我将在混合中添加一个用户控件。用户控件基本上是网格中的TreeView: 其目的是用usercontrol替换上面使用的vanilla treeview,并根据所选内容更改标签内容。所以,我试着