none
TreeViewイベントについて RRS feed

  • 質問

  • OS:Windows10

    開発環境

    VisualStudio2015

    .net Framework 4.5

    言語

    WPF(VB)

    ツリービューにHierarchicalDataTemplateを利用して項目を表示させています。

    この項目をダブルクリックにてイベントを発生させたいのですがイベントが発生しません。

                            <TreeView.ItemContainerStyle>
                                <Style TargetType="{x:Type TreeViewItem}">
                                    <!--<EventSetter Event="MouseDoubleClick" Handler="menuTreeView_MouseDoubleClick"/>-->
                                    <Setter Property="IsExpanded" Value="{Binding Path=IsExpanded, Mode=TwoWay}" />
                                    <Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
                                    <Setter Property="FontWeight" Value="Normal" />
                                    <Style.Triggers>
                                        <Trigger Property="IsSelected" Value="True">
                                            <Setter Property="FontWeight" Value="Bold" />
                                        </Trigger>
                                    </Style.Triggers>
                                </Style>
                            </TreeView.ItemContainerStyle>
                            <TreeView.ItemTemplate>
                                <HierarchicalDataTemplate DataType="local:MenuWindow.MenuNodeItem" ItemsSource="{Binding Children}" >
                                    <TextBlock Text="{Binding Name}" />
                                    
                                    <HierarchicalDataTemplate.ItemContainerStyle>
                                        <Style TargetType="{x:Type TreeViewItem}">
                                            <EventSetter Event="MouseDoubleClick" Handler="menuTreeView_MouseDoubleClick"/>
                                        </Style>
                                    </HierarchicalDataTemplate.ItemContainerStyle>
                                          
                                </HierarchicalDataTemplate>
                            </TreeView.ItemTemplate>
    

    そこで、TreeView.ItemContainerStyleにEventSetterを記述したところ、

    イベントは発生するのですが、項目の階層分イベントが発生します。

    ※3階層目の項目ダブルクリックにて、イベントが3回発生する。

    こちらについて、解決方法をご存知の方はおられませんか?

      

    以上、よろしくお願い致します。

    2017年6月20日 6:25

回答

  • TreeViewItemは大まかにいうと「ヘッダ部分」「下の階層一覧」というの2個の要素で構成されています。
    つまり、TreeViewItemにMouseDoubleClickを設定すると、子の要素のダブルクリックは親の階層のダブルクリックにもなってしまいます。
    そのため、1回のダブルクリックが階層の数だけ発生してしまいます。

    1回だけにするにはTreeViewでDoubleClickイベントを設定するか、HierarchicalDataTemplate内の要素にDoubleClickイベントを設定します。
    #TreeViewItemのテンプレートの書き換えだと大変なので、

    <TreeView ItemsSource="{Binding}" MouseDoubleClick="TreeView_MouseDoubleClick">
        <TreeView.ItemContainerStyle>
            <Style TargetType="{x:Type TreeViewItem}">
                <Setter Property="IsExpanded" Value="{Binding Path=IsExpanded, Mode=TwoWay}" />
                <Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
                <Setter Property="FontWeight" Value="Normal" />
                <Style.Triggers>
                    <Trigger Property="IsSelected" Value="True">
                        <Setter Property="FontWeight" Value="Bold" />
                    </Trigger>
                </Style.Triggers>
            </Style>
        </TreeView.ItemContainerStyle>
                
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate DataType="local:MenuWindow.MenuNodeItem" ItemsSource="{Binding Children}" >
                <ContentControl MouseDoubleClick="TreeViewItemHeader_MouseDoubleClick">
                    <TextBlock Text="{Binding Name}"/>
                </ContentControl>
                        
                <!--<HierarchicalDataTemplate.ItemContainerStyle>
                    このItemContainerStyleはこの階層の下の階層のTreeViewItemのスタイルです
                    ですからこの階層でダブルクリックしてもイベントは何もおきません
                    <Style TargetType="{x:Type TreeViewItem}">
    
                        <EventSetter Event="MouseDoubleClick" Handler="menuTreeView_MouseDoubleClick" />
                    </Style>
                </HierarchicalDataTemplate.ItemContainerStyle>-->
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>           
    </TreeView>

    ''' <summary>TreeViewにDoubleClickイベントを設定する場合</summary>
    Private Sub TreeView_MouseDoubleClick(sender As Object, e As MouseButtonEventArgs)
        Dim d As DependencyObject = e.OriginalSource
        Do While (d IsNot sender)
            If (TypeOf d Is TreeViewItem) Then
                Dim tvi As TreeViewItem = CType(d, TreeViewItem)
                Dim item = TryCast(tvi.DataContext, MenuWindow.MenuNodeItem)
                If (item IsNot Nothing) Then
                    MessageBox.Show(item.Name)
                End If
                Exit Do
            End If
            d = VisualTreeHelper.GetParent(d)
        Loop
    End Sub


    ''' <summary>TreeViewItemのContent内にDoubleClickを設定する場合</summary>
    Private Sub TreeViewItemHeader_MouseDoubleClick(sender As Object, e As MouseButtonEventArgs)
        Dim fe = CType(e.OriginalSource, FrameworkElement)
        Dim item = TryCast(fe.DataContext, MenuWindow.MenuNodeItem)
        If (item IsNot Nothing) Then
            MessageBox.Show(item.Name)
        End If
    End Sub

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    2017年6月20日 9:16

すべての返信

  • TreeViewItemは大まかにいうと「ヘッダ部分」「下の階層一覧」というの2個の要素で構成されています。
    つまり、TreeViewItemにMouseDoubleClickを設定すると、子の要素のダブルクリックは親の階層のダブルクリックにもなってしまいます。
    そのため、1回のダブルクリックが階層の数だけ発生してしまいます。

    1回だけにするにはTreeViewでDoubleClickイベントを設定するか、HierarchicalDataTemplate内の要素にDoubleClickイベントを設定します。
    #TreeViewItemのテンプレートの書き換えだと大変なので、

    <TreeView ItemsSource="{Binding}" MouseDoubleClick="TreeView_MouseDoubleClick">
        <TreeView.ItemContainerStyle>
            <Style TargetType="{x:Type TreeViewItem}">
                <Setter Property="IsExpanded" Value="{Binding Path=IsExpanded, Mode=TwoWay}" />
                <Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
                <Setter Property="FontWeight" Value="Normal" />
                <Style.Triggers>
                    <Trigger Property="IsSelected" Value="True">
                        <Setter Property="FontWeight" Value="Bold" />
                    </Trigger>
                </Style.Triggers>
            </Style>
        </TreeView.ItemContainerStyle>
                
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate DataType="local:MenuWindow.MenuNodeItem" ItemsSource="{Binding Children}" >
                <ContentControl MouseDoubleClick="TreeViewItemHeader_MouseDoubleClick">
                    <TextBlock Text="{Binding Name}"/>
                </ContentControl>
                        
                <!--<HierarchicalDataTemplate.ItemContainerStyle>
                    このItemContainerStyleはこの階層の下の階層のTreeViewItemのスタイルです
                    ですからこの階層でダブルクリックしてもイベントは何もおきません
                    <Style TargetType="{x:Type TreeViewItem}">
    
                        <EventSetter Event="MouseDoubleClick" Handler="menuTreeView_MouseDoubleClick" />
                    </Style>
                </HierarchicalDataTemplate.ItemContainerStyle>-->
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>           
    </TreeView>

    ''' <summary>TreeViewにDoubleClickイベントを設定する場合</summary>
    Private Sub TreeView_MouseDoubleClick(sender As Object, e As MouseButtonEventArgs)
        Dim d As DependencyObject = e.OriginalSource
        Do While (d IsNot sender)
            If (TypeOf d Is TreeViewItem) Then
                Dim tvi As TreeViewItem = CType(d, TreeViewItem)
                Dim item = TryCast(tvi.DataContext, MenuWindow.MenuNodeItem)
                If (item IsNot Nothing) Then
                    MessageBox.Show(item.Name)
                End If
                Exit Do
            End If
            d = VisualTreeHelper.GetParent(d)
        Loop
    End Sub


    ''' <summary>TreeViewItemのContent内にDoubleClickを設定する場合</summary>
    Private Sub TreeViewItemHeader_MouseDoubleClick(sender As Object, e As MouseButtonEventArgs)
        Dim fe = CType(e.OriginalSource, FrameworkElement)
        Dim item = TryCast(fe.DataContext, MenuWindow.MenuNodeItem)
        If (item IsNot Nothing) Then
            MessageBox.Show(item.Name)
        End If
    End Sub

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    2017年6月20日 9:16
  • 丁寧な解説、サンプルソースありがとうございます。

    おかげでやりたいことが実現できました。

    WPFについては基礎的な知識がないまま開発を任されてしまったため、助かりました。

    また質問させていただくこともあると思いますが、よろしくお願い致します。

    2017年6月23日 0:23