2013-03-16 3 views
0

선택한 Item에서 MasterDetails로 TreeView를 만들고 싶습니다.MasterDetails 및 ToggleButton이있는 TreeView

부모가 확장 되어도 하위 항목이 내 SelectedItem에 표시되지 않습니다. 어떻게 든 HierarchicalDataTemplate은 손실 된 것처럼 보입니다.

아마도 나는 <TreeView.ItemTemplate>의 HierarchicalDataTemplate에 잘못되었습니다. ItemsPanelTemplate 또는 이와 비슷한 항목부터 시작해야합니까? 지금 당장 실마리가 없어.

<Window x:Class="TreeViewMasterDetails.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:TreeViewMasterDetails" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <Grid.Resources> 
      <SolidColorBrush x:Key="GlyphBrush" Color="#444" /> 
      <BooleanToVisibilityConverter x:Key="booltoVisibilityConverter" /> 

      <PathGeometry x:Key="TreeArrow"> 
       <PathGeometry.Figures> 
        <PathFigureCollection> 
         <PathFigure IsFilled="True" 
          StartPoint="0 0" 
          IsClosed="True"> 
          <PathFigure.Segments> 
           <PathSegmentCollection> 
            <LineSegment Point="0 6"/> 
            <LineSegment Point="6 0"/> 
           </PathSegmentCollection> 
          </PathFigure.Segments> 
         </PathFigure> 
        </PathFigureCollection> 
       </PathGeometry.Figures> 
      </PathGeometry> 

      <Style x:Key="ExpandCollapseToggleStyle" 
      TargetType="{x:Type ToggleButton}"> 
       <Setter Property="Focusable" 
       Value="False"/> 
       <Setter Property="Width" 
       Value="16"/> 
       <Setter Property="Height" 
       Value="16"/> 
       <Setter Property="Template"> 
        <Setter.Value> 
         <ControlTemplate TargetType="{x:Type ToggleButton}"> 
          <Border Width="16" 
          Height="16" 
          Background="Transparent" 
          Padding="5,5,5,5"> 
           <Path x:Name="ExpandPath" 
           Fill="Transparent" 
           Stroke="#FF989898" 
           Data="{StaticResource TreeArrow}"> 
            <Path.RenderTransform> 
             <RotateTransform Angle="135" 
               CenterX="3" 
               CenterY="3"/> 
            </Path.RenderTransform> 
           </Path> 
          </Border> 
          <ControlTemplate.Triggers> 
           <Trigger Property="IsMouseOver" 
           Value="True"> 
            <Setter TargetName="ExpandPath" 
            Property="Stroke" 
            Value="#FF1BBBFA"/> 
            <Setter TargetName="ExpandPath" 
            Property="Fill" 
            Value="Transparent"/> 
           </Trigger> 

           <Trigger Property="IsChecked" 
           Value="True"> 
            <Setter TargetName="ExpandPath" 
            Property="RenderTransform"> 
             <Setter.Value> 
              <RotateTransform Angle="180" 
                CenterX="3" 
                CenterY="3"/> 
             </Setter.Value> 
            </Setter> 
            <Setter TargetName="ExpandPath" 
            Property="Fill" 
            Value="#FF595959"/> 
            <Setter TargetName="ExpandPath" 
            Property="Stroke" 
            Value="#FF262626"/> 
           </Trigger> 
          </ControlTemplate.Triggers> 
         </ControlTemplate> 
        </Setter.Value> 
       </Setter> 
      </Style> 

      <ControlTemplate TargetType="{x:Type TreeViewItem}" x:Key="selectedItemTemplate"> 
       <Grid Height="Auto" Background="SkyBlue"> 
        <Grid.RowDefinitions> 
         <RowDefinition Height="Auto"></RowDefinition> 
         <RowDefinition Height="Auto"></RowDefinition> 
         <RowDefinition Height="Auto"></RowDefinition> 
        </Grid.RowDefinitions> 
        <Grid.ColumnDefinitions> 
         <ColumnDefinition Width="20"></ColumnDefinition> 
         <ColumnDefinition Width="Auto"></ColumnDefinition> 
        </Grid.ColumnDefinitions> 
        <ToggleButton x:Name="Expander" 
             Style="{StaticResource ExpandCollapseToggleStyle}" 
             IsChecked="{Binding Path=IsExpanded,RelativeSource={RelativeSource TemplatedParent}}" 
             ClickMode="Press" 
             Visibility="{Binding Path=HasItems,RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource booltoVisibilityConverter}}"/> 

        <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Id}"></TextBlock> 
        <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Name}"></TextBlock> 
        <TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Description}"></TextBlock> 
       </Grid> 
      </ControlTemplate> 
     </Grid.Resources> 

     <TreeView Height="Auto" 
        HorizontalAlignment="Stretch" 
        Margin="10" 
        VerticalAlignment="Stretch" 
        Width="Auto" 
        ItemsSource="{Binding Items}"> 
      <TreeView.ItemContainerStyle> 
       <Style TargetType="TreeViewItem"> 
        <Style.Triggers> 
         <Trigger Property="IsSelected" Value="True"> 
          <Setter Property="Template" Value="{StaticResource selectedItemTemplate}"/> 
         </Trigger> 
        </Style.Triggers> 
       </Style> 
      </TreeView.ItemContainerStyle> 
      <TreeView.ItemTemplate> 
       <HierarchicalDataTemplate DataType="x:Type local:NodeViewModel" ItemsSource="{Binding Children}"> 
        <Grid> 
         <Grid.RowDefinitions> 
          <RowDefinition Height="20*" /> 
         </Grid.RowDefinitions> 
         <Grid.ColumnDefinitions> 
          <ColumnDefinition Width="100*" /> 
          <ColumnDefinition Width="100*" /> 
          <ColumnDefinition Width="100*" /> 
         </Grid.ColumnDefinitions> 

         <TextBlock Grid.Column="0" Text="{Binding Id}"></TextBlock> 
         <TextBlock Grid.Column="1" Text="----"></TextBlock> 
         <TextBlock Grid.Column="2" Text="{Binding Name}"></TextBlock> 
        </Grid> 

       </HierarchicalDataTemplate> 
      </TreeView.ItemTemplate> 
     </TreeView> 
    </Grid> 
</Window> 

는 XAML의 매시브 블록을 용서하십시오,하지만 지금 나는 원인이 자리하고있는 곳 모른다 :

여기 내 XAML입니다.

그리고 내 뷰 모델 :

public class NodeViewModel : ViewModelBase 
{ 
    public string Id { get; set; } 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public bool IsExpanded { get; set; } 
    public bool HasChildren // perhaps this can be replaced by HasItems in TemplatedParent? 
    { 
     get 
     { 
      if (Children != null) 
      { 
       Children.Any(); 
      } 

      return false; 
     } 
    } 

    public ObservableCollection<NodeViewModel> Children { get; set; } 
} 
내 HierarchicalDataTemplate와 아이를 표시 할 수있는 방법

? 왜 길을 잃은거야?

업데이트 내 TreeViewItem 스타일의 세터가 선택 에 참으로 IsExpanded 설정에 추가하고 ToggleButton을이 권리를 표시 할 것 같다.

계층 적 데이터 템플릿을 처리하는 방법을 찾을 수있는 유용한 자습서가 있습니까?

내가 어떻게 할 수 있는지에 대한 아이디어는 높이 평가 될 것입니다!

답변

1

토글 버튼을 사용하여 트리보기 항목을 에뮬레이션하려고했습니다. 그렇게 할 수있는 방법이있을 것이라고 확신하지만, 복잡합니다. 템플릿 외부에있는 확장 버튼을 사용하여 살 수 있다면 다음 해결책을 시도해보십시오. treeview 항목의 비주얼 스타일을 변경하면 이제 HierarchicalDataTemplate에 내장됩니다. HierarchicalDataTemplate이 재산 Children을 사용하는 반면

enter image description here

당신은, 당신은 공개하지 않은 뷰 모델의 재산 Items에 트 리뷰를 바인딩, 내가 변화했다는 것을 나는 '루트'로 또한 NodeViewModel을 사용하기 때문에 ViewModel.

DataTemplateSelector를 사용하여 동일한 결과를 얻을 수 있다고 생각합니다.

XAML :

<UserControl.DataContext> 
    <local:NodeViewModel /> 
</UserControl.DataContext> 
<Grid> 
    <Grid.Resources> 
     <DataTemplate x:Key="notSelectedItemTemplate" DataType="{x:Type local:NodeViewModel}" > 
      <Grid> 
       <Grid.RowDefinitions> 
        <RowDefinition Height="20*" /> 
       </Grid.RowDefinitions> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition Width="100*" /> 
        <ColumnDefinition Width="100*" /> 
        <ColumnDefinition Width="100*" /> 
       </Grid.ColumnDefinitions> 

       <TextBlock Grid.Column="0" Text="{Binding Id}"></TextBlock> 
       <TextBlock Grid.Column="1" Text="----"></TextBlock> 
       <TextBlock Grid.Column="2" Text="{Binding Name}"></TextBlock> 
      </Grid> 
     </DataTemplate> 

     <DataTemplate x:Key="selectedItemTemplate" DataType="{x:Type local:NodeViewModel}"> 
      <Grid Height="Auto" Background="SkyBlue" TextElement.Foreground="Black"> 
       <Grid.RowDefinitions> 
        <!--<RowDefinition Height="Auto"></RowDefinition>--> 
        <RowDefinition Height="Auto"></RowDefinition> 
        <RowDefinition Height="Auto"></RowDefinition> 
       </Grid.RowDefinitions> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition Width="20"></ColumnDefinition> 
        <ColumnDefinition Width="Auto"></ColumnDefinition> 
       </Grid.ColumnDefinitions> 

       <!--<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Id}"></TextBlock>--> 
       <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Name}"></TextBlock> 
       <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Description}"></TextBlock> 
      </Grid> 
     </DataTemplate> 
    </Grid.Resources> 

    <TreeView Height="Auto" HorizontalAlignment="Stretch" Margin="10" VerticalAlignment="Stretch" Width="Auto" ItemsSource="{Binding Children}"> 
     <TreeView.Resources> 
      <!-- remove normal selected item background --> 
      <SolidColorBrush Color="Transparent" x:Key="{x:Static SystemColors.HighlightBrushKey}"/> 
     </TreeView.Resources> 
     <TreeView.ItemContainerStyle> 
      <Style TargetType="{x:Type TreeViewItem}"> 
       <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" /> 
      </Style> 
     </TreeView.ItemContainerStyle> 
     <TreeView.ItemTemplate> 
      <HierarchicalDataTemplate DataType="{x:Type local:NodeViewModel}" ItemsSource="{Binding Children}"> 
       <ContentPresenter x:Name="item" ContentTemplate="{StaticResource notSelectedItemTemplate}" /> 
       <HierarchicalDataTemplate.Triggers> 
        <DataTrigger Binding="{Binding IsSelected}" Value="True"> 
         <Setter TargetName="item" Property="ContentTemplate" Value="{StaticResource selectedItemTemplate}" /> 
        </DataTrigger> 
       </HierarchicalDataTemplate.Triggers> 
      </HierarchicalDataTemplate> 
     </TreeView.ItemTemplate> 
    </TreeView> 
</Grid> 

NodeViewModel (추가에 isSelected 속성) :

public class NodeViewModel : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    private void OnPropertyChanged(string propertyName) 
    { 
     if (this.PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 

    private ObservableCollection<NodeViewModel> _children; 
    public ObservableCollection<NodeViewModel> Children { get { return _children; } set { _children = value; OnPropertyChanged("Children"); } } 


    private string _id; 
    public string Id { get { return _id; } set { _id = value; OnPropertyChanged("ID"); } } 
    private string _name; 
    public string Name { get { return _name; } set { _name = value; OnPropertyChanged("ID"); } } 
    private string _description; 
    public string Description { get { return _description; } set { _description = value; OnPropertyChanged("Description"); } } 
    private bool _isExpanded; 
    public bool IsExpanded { get { return _isExpanded; } set { _isExpanded = value; OnPropertyChanged("IsExpanded"); } } 
    private bool _isSelected; 
    public bool IsSelected { get { return _isSelected; } set { _isSelected = value; OnPropertyChanged("IsSelected"); } } 
    public bool HasChildren // perhaps this can be replaced by HasItems in TemplatedParent? 
    { 
     get 
     { 
      if (Children != null) 
      { 
       Children.Any(); 
      } 

      return false; 
     } 
    } 

    private static bool _setData = true; // hack for example data 

    public NodeViewModel() 
    { 
     if (_setData) 
     { 
      _setData = false; 
      SetExampleData(); 
     } 
    } 

    public void SetExampleData() 
    { 
     Children = new ObservableCollection<NodeViewModel>() 
     { 
      new NodeViewModel() { Name = "1", Description = "One" }, 
      new NodeViewModel() { Name = "2", Description = "Two" }, 
      new NodeViewModel() { Name = "3", Description = "Three" }, 
      new NodeViewModel() { Name = "4", Description = "Four" }, 
      new NodeViewModel() { Name = "5", Description = "Five" }, 
      new NodeViewModel() { Name = "6", Description = "Six" }, 
      new NodeViewModel() { Name = "7", Description = "Seven" }, 
      new NodeViewModel() { Name = "8", Description = "Eight" } 
     }; 

     Children[0].Children = new ObservableCollection<NodeViewModel>() 
     { 
      new NodeViewModel() { Name = "1.1", Description="One.One" }, 
      new NodeViewModel() { Name = "1.2", Description="One.Two" }, 
      new NodeViewModel() { Name = "1.3", Description="One.Three" } 
     }; 

     Children[0].Children[0].Children = new ObservableCollection<NodeViewModel>() 
     { 
      new NodeViewModel() { Name = "1.1.1", Description="One.One.One" }, 
      new NodeViewModel() { Name = "1.1.2", Description="One.One.Two" }, 
     }; 

     Children[1].Children = new ObservableCollection<NodeViewModel>() 
     { 
      new NodeViewModel() { Name = "2.1", Description="Two.One" }, 
      new NodeViewModel() { Name = "2.2", Description="Two.Two" }, 
     }; 
    } 
} 
+0

당신, 내가 노드를 포함하고 하나를 게시하지 못했지만, nodeviewmodel 등을 가진 다른 뷰 모델을 권리가있다 뿌리는 괜찮아. 고맙습니다. 작동하지 않는 유일한 것은 선택된 노드를 확장하는 것입니다. 그것을 성취하는 방법? –

+0

귀하의 의견으로 인해 나는 귀하의 문제를 이해했습니다. 나는 그것을 해결하기위한 답을 편집했다. –

+0

원더풀! 아주 잘 작동합니다! 고마워요! –