2016-10-05 2 views
0

DataTemplate을 사용자 정의하려는 간단한 TreeView이 있습니다. 원하는대로 표시되지만 TreeViewItem을 선택할 때 TreeView의 텍스트를 클릭하면 강조 표시가 작동하지 않습니다.TreeView에서 사용자 정의 DataTemplate 강조 표시

TreeView selection issue

소스가 똑바로 앞으로 꽤, 그래서 난 그냥 스타일링 연결 누락 같은데요 : 내가 텍스트의 왼쪽에 단지 선택한다면, 그것은 작동

을 XAML

<TreeView x:Name="treeView" 
      ItemsSource="{Binding TreeViewItems}" 
      Grid.Row="0"> 
     <TreeView.ItemTemplate> 
     <HierarchicalDataTemplate ItemsSource="{Binding Path=MenuItems}"> 
      <TreeViewItem Header="{Binding Header}"> 
       <TreeViewItem.InputBindings> 
        <MouseBinding MouseAction="LeftClick" 
           Command="{Binding Command}" /> 
       </TreeViewItem.InputBindings> 
      </TreeViewItem> 
     </HierarchicalDataTemplate> 
     </TreeView.ItemTemplate> 
    </TreeView> 

은 내가 XAML이 추가 시도했다, 그러나 그것은 도움이 일부러 :

 <TreeView.ItemContainerStyle> 
     <Style TargetType="{x:Type TreeViewItem}" 
       BasedOn="{StaticResource {x:Type TreeViewItem}}" /> 
     </TreeView.ItemContainerStyle> 

TreeViewModel TreeViewItemsSource의 각 항목에 대한 TreeViewItem을 만드는, 그래서 TreeView가 이미 당신을 위해 만든 하나에 있지 둥지 또 다른 TreeViewItem을 할 수있다

public class MenuItemViewModel : BaseNotifyModel 
    { 
     public MenuItemViewModel() 
     { 
     MenuItems = 
      new ObservableCollection<MenuItemViewModel>(); 
     } 

     public String Header 
     { 
     get 
     { 
      return Get<String>(); 
     } 
     set 
     { 
      Set(value); 
     } 
     } 

     public ICommand Command 
     { 
     get 
     { 
      return Get<ICommand>(); 
     } 
     set 
     { 
      Set(value); 
     } 
     } 

     public ObservableCollection<MenuItemViewModel> MenuItems 
     { 
     get 
     { 
      return Get<ObservableCollection<MenuItemViewModel>>(); 
     } 
     set 
     { 
      Set(value); 
     } 
     } 
    } 
+0

왜 TreeViewItem의 데이터 템플릿에 TreeViewItem을 넣고 있습니까? 왜 두 개의 중첩 된 트리보기 항목이 필요합니까? –

+0

템플릿에 일반 TextBlock을 넣고 다른 TreeViewItem은 넣지 마십시오. – Evk

+0

ItemContainerStyle에서 입력 바인딩을 수행하고 Header를 스타일의 MenuItemViewModel.Header에 바인드하고 데이터 템플릿에서 '를 버리면됩니다. 또는 Evk에서 말하는 것처럼 TextBlock 또는 Label을 사용하십시오. –

답변

0

@Ed Plunket 및 @Evk의 도움으로 작동 할 해결책을 찾았습니다. ContentPresenter으로 변경 한 후 Interaction.Triggers을 사용하여 MouseLeftButtonUp 작업에서 명령을 호출했습니다.

<TreeView ItemsSource="{Binding TreeViewItems}"> 
     <TreeView.ItemTemplate> 
     <HierarchicalDataTemplate ItemsSource="{Binding Path=MenuItems}"> 
      <ContentPresenter Content="{Binding Header}"> 
       <i:Interaction.Triggers> 
        <i:EventTrigger EventName="MouseLeftButtonUp"> 
        <i:InvokeCommandAction Command="{Binding Path=DataContext.Command, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TreeViewItem}}}" /> 
        </i:EventTrigger> 
       </i:Interaction.Triggers> 
      </ContentPresenter> 
     </HierarchicalDataTemplate> 
     </TreeView.ItemTemplate> 
    </TreeView> 
1

public class TreeViewModel : BaseNotifyModel, ITreeViewModel 
    { 
     public TreeViewModel(ITreeViewService menuService) 
     { 
     TreeViewItems = 
      new ReadOnlyObservableCollection<MenuItemViewModel>(menuService.TreeViewMenu); 
     } 

     public ReadOnlyObservableCollection<MenuItemViewModel> TreeViewItems 
     { 
     get 
     { 
      return Get<ReadOnlyObservableCollection<MenuItemViewModel>>(); 
     } 
     private set 
     { 
      Set(value); 
     } 
     } 
    } 

MenuItemViewModel. 그것은 어떤 목적을위한 것이 아닙니다. 템플릿은 기존 TreeViewItemDataContext (여기서는 MenuItemViewModel)의 내용을 표시하는 방법을 제공해야합니다.

트리보기 항목에 Header 속성을 표시하려고합니다. 그러니 그냥해라. 공상적인 것, 단지 Label 또는 ContentControl이거나, String 인 경우 TextBlock (임의의 내용의 유연성을 갖는 것은 WPF에서 많은 즐거움이 있지만). 사용자가 내용을 클릭하면 명령이 실행됩니다. 사용자가 트리에서 볼 수있는 유일한 내용은 내용입니다. 이 항목은 TreeViewItem 항목 중 유일하게 보이는 부분이므로 사용자가 클릭 할 항목입니다.

문제 번호 2 : 입력 바인딩이 LeftClick이되면 TreeView의 선택이 중단됩니다. 그 방법으로 여기에서 당신이 거기에 도착할 수 없다는 것이 나에게 나타납니다.

<TreeView.ItemTemplate> 
    <HierarchicalDataTemplate ItemsSource="{Binding Path=MenuItems}"> 
     <ContentControl 
      Content="{Binding Header}" 
      Background="Transparent" 
      > 
     </ContentControl> 
    </HierarchicalDataTemplate> 
</TreeView.ItemTemplate> 
<TreeView.ItemContainerStyle> 
    <Style TargetType="TreeViewItem" BasedOn="{StaticResource {x:Type TreeViewItem}}"> 
     <EventSetter Event="Selected" Handler="MenuTreeViewItem_Click" /> 
    </Style> 
</TreeView.ItemContainerStyle> 

Codebehind가

private void MenuTreeViewItem_Click(object sender, RoutedEventArgs e) 
{ 
    ((MenuItemViewModel)((FrameworkElement)sender).DataContext).Command.Execute(null); 
} 

There is a way to bind an event to a command in pure XAML하지만 일부 C# 코드 (LOL)가 필요합니다 :

<TreeView.ItemTemplate> 
    <HierarchicalDataTemplate ItemsSource="{Binding Path=MenuItems}"> 
     <ContentControl 
      Content="{Binding Header}" 
      Background="Transparent" 
      > 
      <ContentControl.InputBindings> 
       <!-- This invokes the command, but breaks selection --> 
       <MouseBinding MouseAction="LeftClick" 
          Command="{Binding Command}" /> 
      </ContentControl.InputBindings> 
     </ContentControl> 
    </HierarchicalDataTemplate> 
    </TreeView.ItemTemplate> 

다음은 무엇을 할 수 있습니다. 하지만 제 말은 순수한 XAML입니다. 즉, 코드 숨김에있는보기 흉한 이벤트 처리기가 아니라 일반적으로 재사용 가능한 좋은 첨부 된 동작입니다. 대신 위의 작업을 수행하지만 코드에서 코드를 사용하면 눈을 피할 수 있고 순수한 XAML에서 다시 사용할 수 있습니다.

+0

자, 이제 알겠습니다. 그러나 이것을 시도 할 때 명령은 텍스트를 클릭 할 때 작동하지만 텍스트를 강조 표시하지 않습니다 (두 번 클릭하지 않는 한). – SwDevMan81

+0

@ SwDevMan81 업데이트되었습니다. 명시 적으로'Background'를'Transparent'로 설정하십시오. 'ContentControl'을'Label'으로 변경하면 역시 작동합니다; 기본적으로 '투명한'배경을 가지고 있습니다. 유일한 단서는 명령이 키보드 포커스를 방해하는 작업을 수행하는 경우 선택 사항을 무시하고 중단한다는 것입니다. 예를 들어, 내 테스트 코드 명령이 원래 MessageBox를 팝업하여 선택을 방지했습니다. TreeView가 무슨 일이 일어나고 있는지를 알기 전에 포커스를 훔쳐 갔다고 생각합니다. –

+2

@EdPlunkett, 배경 설정이 도움이되지 않습니다. 클릭 이벤트는 LeftClick 처리기에서 계속 먹게되므로 항목이 강조 표시되지 않습니다. – Evk