2017-02-18 8 views
0

이질족 노드 유형이있는 TreeView가 있습니다. 각 노드 유형은 HierarchicalDataTemplate을 사용하여 XAML에서 구성됩니다.WPF의 전체 TreeViewItem 행에 ContextMenu 표시

일부 노드에는 ContextMenu가 있으며 노드의 유형에 따라 다릅니다. ContextMenus는 XAML의 정적 리소스로 정의되며 HierarchicalDataTemplate의 DockPanel에 연결됩니다.

또한 ControlTemplate은 다음 StackOverflow 질문 https://stackoverflow.com/a/672123/1626109에서 bendewey가 설명한 TreeViewItem에 사용하고 있습니다. 이 ControlTemplate은 전체 TreeViewItem이 선택 될 때 강조되도록 정의됩니다. 라인의 일부를 왼쪽 클릭하면 항목이 선택됩니다.

대조적으로 HierarchicalDataTemplate에 정의 된 컨텍스트 메뉴는 해당 줄의 오른쪽 부분에서만 작동합니다.

전 라인에서 사용할 수 있도록 ContextMenus를 구성하는 방법을 찾고 있습니다.

이것은 HierarchicalDataTemplate에 정의 된 TemplateBinding을 사용하여 ControlTemplate의 요소에 컨텍스트 메뉴를 연결해야하는 것처럼 보입니다. 그러나 어떻게해야 할지를 알 수 없습니다.

그런데 Visual Studio의 솔루션 탐색기에는 이와 같은 동작이 있습니다. 상황에 맞는 메뉴는 노드 유형에 따라 다르며 확장/축소 버튼 왼쪽을 포함하여 전체 항목에서 사용할 수 있습니다.

답변

1

은 (편집 됨) 당신은 TreeViewItem 스타일의 Grid의 두 열을 제거해야합니다

<Window.Resources> 
    <local:LeftMarginMultiplierConverter Length="19" x:Key="lengthConverter" /> 
    <SolidColorBrush x:Key="GlyphBrush" Color="#444" /> 
    <Style x:Key="ExpandCollapseToggleStyle" TargetType="ToggleButton"> 
     <Setter Property="Focusable" Value="False"/> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="ToggleButton"> 
        <Grid Width="15" Height="13" 
     Background="Transparent"> 
         <Path x:Name="ExpandPath" 
     HorizontalAlignment="Left" 
     VerticalAlignment="Center" 
     Margin="1,1,1,1" 
     Fill="{StaticResource GlyphBrush}" 
     Data="M 4 0 L 8 4 L 4 8 Z"/> 
        </Grid> 
        <ControlTemplate.Triggers> 
         <Trigger Property="IsChecked" 
      Value="True"> 
          <Setter Property="Data" 
      TargetName="ExpandPath" 
      Value="M 0 4 L 8 4 L 4 8 Z"/> 
         </Trigger> 
        </ControlTemplate.Triggers> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
    <Style x:Key="TreeViewItemFocusVisual"> 
     <Setter Property="Control.Template"> 
      <Setter.Value> 
       <ControlTemplate> 
        <Border> 
         <Rectangle Margin="0,0,0,0" 
      StrokeThickness="5" 
      Stroke="Black" 
      StrokeDashArray="1 2" 
      Opacity="0"/> 
        </Border> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
    <Style x:Key="{x:Type TreeViewItem}" 
TargetType="{x:Type TreeViewItem}"> 
     <Setter Property="Background" 
    Value="Transparent"/> 
     <Setter Property="HorizontalContentAlignment" 
    Value="{Binding Path=HorizontalContentAlignment, 
      RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/> 
     <Setter Property="VerticalContentAlignment" 
    Value="{Binding Path=VerticalContentAlignment, 
      RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/> 
     <Setter Property="Padding" 
    Value="1,0,0,0"/> 
     <Setter Property="Foreground" 
    Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/> 
     <Setter Property="FocusVisualStyle" 
    Value="{StaticResource TreeViewItemFocusVisual}"/> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="{x:Type TreeViewItem}"> 
        <ControlTemplate.Resources> 
         <local:LeftMarginMultiplierConverter Length="19" x:Key="lengthConverter" /> 
        </ControlTemplate.Resources> 
        <StackPanel> 
         <Border Name="Bd" 
      Background="{TemplateBinding Background}" 
      BorderBrush="{TemplateBinding BorderBrush}" 
      BorderThickness="{TemplateBinding BorderThickness}" 
      Padding="{TemplateBinding Padding}"> 
          <Grid> 
           <ToggleButton Panel.ZIndex="2" x:Name="Expander" 
               HorizontalAlignment="Left" 
       Style="{StaticResource ExpandCollapseToggleStyle}" 
       IsChecked="{Binding Path=IsExpanded, 
          RelativeSource={RelativeSource TemplatedParent}}" 
       ClickMode="Press" 
               Margin="{Binding Converter={StaticResource lengthConverter}, ConverterParameter=0, 
          RelativeSource={RelativeSource TemplatedParent}}"/> 

           <ContentPresenter x:Name="PART_Header" ContentSource="Header" 
        HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"> 
           </ContentPresenter> 
          </Grid> 
         </Border> 
         <ItemsPresenter x:Name="ItemsHost" /> 
        </StackPanel> 
        <ControlTemplate.Triggers> 
         <Trigger Property="IsExpanded" 
      Value="false"> 
          <Setter TargetName="ItemsHost" 
      Property="Visibility" 
      Value="Collapsed"/> 
         </Trigger> 
         <Trigger Property="HasItems" 
      Value="false"> 
          <Setter TargetName="Expander" 
      Property="Visibility" 
      Value="Hidden"/> 
         </Trigger> 
         <MultiTrigger> 
          <MultiTrigger.Conditions> 
           <Condition Property="HasHeader" 
       Value="false"/> 
           <Condition Property="Width" 
       Value="Auto"/> 
          </MultiTrigger.Conditions> 
          <Setter TargetName="PART_Header" 
      Property="MinWidth" 
      Value="75"/> 
         </MultiTrigger> 
         <MultiTrigger> 
          <MultiTrigger.Conditions> 
           <Condition Property="HasHeader" 
       Value="false"/> 
           <Condition Property="Height" 
       Value="Auto"/> 
          </MultiTrigger.Conditions> 
          <Setter TargetName="PART_Header" 
      Property="MinHeight" 
      Value="19"/> 
         </MultiTrigger> 
         <Trigger Property="IsSelected" 
      Value="true"> 
          <Setter TargetName="Bd" 
      Property="Background" 
      Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/> 
          <Setter Property="Foreground" 
      Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/> 
         </Trigger> 
         <MultiTrigger> 
          <MultiTrigger.Conditions> 
           <Condition Property="IsSelected" 
       Value="true"/> 
           <Condition Property="IsSelectionActive" 
       Value="false"/> 
          </MultiTrigger.Conditions> 
          <Setter TargetName="Bd" 
      Property="Background" 
      Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/> 
          <Setter Property="Foreground" 
      Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/> 
         </MultiTrigger> 
         <Trigger Property="IsEnabled" 
      Value="false"> 
          <Setter Property="Foreground" 
      Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> 
         </Trigger> 
        </ControlTemplate.Triggers> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</Window.Resources> 

그러나, 이것은 헤더-항목을 준비를 왜곡합니다. 따라서 HierarchicalDataTemplate 부분에 여백을 조정해야합니다 컨버터의 파라미터는 1

public class LeftMarginMultiplierConverter : IValueConverter 
{ 
    public double Length { get; set; } 

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     var item = value as TreeViewItem; 
     if (item == null) 
      return new Thickness(0); 
     int extra = int.Parse(parameter.ToString()); 
     var t = item.GetDepth(); 
     return new Thickness(Length * (item.GetDepth() + extra), 0, 0, 0); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new System.NotImplementedException(); 
    } 
} 

경우에는 컨버터를 조정해야

<TreeView Margin="50" HorizontalContentAlignment="Stretch" DataContext="{Binding}" ItemsSource="{Binding Models}"> 
    <TreeView.ItemTemplate> 
     <HierarchicalDataTemplate DataType="{x:Type local:Model}" ItemsSource="{Binding Models}"> 
      <Border Background="Transparent"> 
       <TextBlock Margin="{Binding Converter={StaticResource lengthConverter}, ConverterParameter=1, 
                   RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=TreeViewItem}}" 
          Text="{Binding Name}" /> 
       <Border.ContextMenu> 
        <ContextMenu> 
         <MenuItem Header="dddd"/> 
        </ContextMenu> 
       </Border.ContextMenu> 
      </Border> 
     </HierarchicalDataTemplate> 
    </TreeView.ItemTemplate> 
</TreeView> 

주 계정에 필요한 추가 마진을 취할 항목의 깊이에 1 포인트를 추가합니다. 나는 헤더 부분에 사용합니다.

또 다른 방법은 TreeViewItemStyleContentPresenterDataTemplate을 추가하는 것입니다. ContextMenu를 바인딩하는 방법을 모르지만,이 방법을 선호합니다.

+0

그건 문제가되지 않습니다. TreeViewItem에 대한 ControlTemplate은 트리 깊이에 따라 여백을 정의한 다음 확장/축소 버튼을 클릭 한 다음 DataTemplate이있는 ContentPresenter를 제공합니다. 컨텍스트 메뉴가 전체 라인에 있어야하므로 ControlTemplate (테두리, 그리드 또는 일부 새 요소)에 정의해야하지만 HierarchicalDataTemplate의 정의에 바인딩해야합니다. –

+0

괜찮습니다. 편집을 참조하십시오. – Ron

+0

감사합니다. 들여 쓰기에 대한 책임을 DataTemplates 및 HierarchicalDataTemplates로 옮기는 것에 대해 다소 불만을 가지고 있습니다. 내 직감 반작용은 그것이 거기에 속하지 않는다고 말한다. (그러나 ContextMenu는 해당 부분에 속하지 않는다고 주장 할 수도 있습니다.) –