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

时间:2015-06-05 14:17:00

标签: wpf vb.net treeview selecteditem

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

我遇到的问题是项目未被正确取消选择,导致在树视图中选择多个项目。

这是树视图的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除了调试打印转换后的值并传递convert-和convertback值外什么都不做。

接下来是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项。现在我单击Action 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,应该如此。 现在我点击Action 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 个答案:

答案 0 :(得分:0)

对谁感兴趣......

我不太明白为什么代码不能正常工作。但显然点击的动作项目未被正确取消选择。而不是调用这些行:

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

直接在MyTreeviewItem_SelectedChanged我现在调用一个计时器。在timer_elapsed事件中,我调用了四行。 显然,在调用代码选择它的父代时,动作项的主要选择没有完成。这是一个丑陋的解决方法,但它对我有用......