2015-05-08 30 views
1

我正在构建一个设置窗口,其左侧为TreeView,右侧为TabControl - 布局基于Microsoft Visual Studio选项对话框。从嵌套tabcontrols填充树形图

TabControl有3个TabItems,所以3个标签。 TabItems中的每一个都包含一个TabControl,其中有两个TabItems。我打算稍后隐藏TabControl标签,但要回TreeView,它看起来就像这样:

  • 选项组中的1
    • 子选项组中的1
    • 子选项组2
  • 选项组2
    • 子选项组1
    • 子选项第2组
  • 选项组3
    • 子选项组中的1
    • 子选项组2

在我的XAML,一切都在视觉上确定。我试图找出这个代码隐藏。

我想拥有它,因此单击TreeView中的项目将导致相应的TabItem变为活动状态。我如何获得Treeview的选定项目/节点并使所有TabControls都有反应?

我在质疑这是否是最好的方法。我会保持TreeView项和选项卡(树)项的TabControlTabItems ...

回答

0

表示

让我们来定义一些类作为模型为我们的嵌套控件。它基本上是一棵树,那里的儿童传播到他们的父母他们IsSelected属性的变化:

public class TabItemModel : INotifyPropertyChanged 
{ 
    private TabItemModel m_parent; 
    private Boolean m_IsSelected; 

    public TabItemModel(String name) : this(name, null) 
    { 
    } 

    public TabItemModel(String name, IEnumerable<TabItemModel> children) 
    { 
     this.Name = name; 

     this.Children = new ObservableCollection<TabItemModel>(children ?? Enumerable.Empty<TabItemModel>()); 

     foreach (var child in this.Children) 
     { 
      child.m_parent = this; 
     } 
    } 

    public String Name 
    { 
     get; 
     set; 
    } 

    public ObservableCollection<TabItemModel> Children 
    { 
     get; 
     private set; 
    } 

    public Boolean IsSelected 
    { 
     get 
     { 
      return this.m_IsSelected; 
     } 
     set 
     { 
      if (value == this.m_IsSelected) 
       return; 

      if (this.m_parent != null) 
       this.m_parent.IsSelected = value; 

      this.m_IsSelected = value; 

      this.OnPropertyChanged(); 
     } 
    } 

    protected void OnPropertyChanged([CallerMemberName]String propertyName = null) 
    { 
     var propChangedDelegate = this.PropertyChanged; 

     if (propChangedDelegate == null) 
      return; 

     propChangedDelegate(this, 
      new PropertyChangedEventArgs(propertyName)); 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
} 

主视图模型

我们需要一些主视图模型将:

  1. 含有这种TabItemModels
  2. 提供选定的tabitemmodel属性以与树视图中的selectedItem进行互操作

代码:

public class TabsViewModel 
{ 
    public TabsViewModel() 
    { 
     this.Items = GetItems(); 
    } 

    private TabItemModel _SelectedItem; 

    public TabItemModel SelectedItem 
    { 
     get 
     { 
      return this._SelectedItem; 
     } 
     set 
     { 
      if (value == this._SelectedItem) 
       return; 

      if (value != null) 
      { 
       if (this._SelectedItem != null) 
        this._SelectedItem.IsSelected = false; 

       value.IsSelected = true; 
      } 

      this._SelectedItem = value; 
     } 
    } 

    public ObservableCollection<TabItemModel> Items 
    { 
     get; 
     private set; 
    } 

    private ObservableCollection<TabItemModel> GetItems() 
    { 
     return new ObservableCollection<TabItemModel>() 
     { 
      new TabItemModel("Tab 1", 
       new TabItemModel[] 
       { 
        new TabItemModel("Tab 1 - SubTab 1"), 
        new TabItemModel("Tab 1 - SubTab 2") 
       }), 
      new TabItemModel("Tab 2", 
       new TabItemModel[] 
       { 
        new TabItemModel("Tab 2 - SubTab 1"), 
        new TabItemModel("Tab 2 - SubTab 2") 
       }), 
      new TabItemModel("Tab 3", 
       new TabItemModel[] 
       { 
        new TabItemModel("Tab 3 - SubTab 1"), 
        new TabItemModel("Tab 3 - SubTab 2") 
       }) 
     }; 
    } 
} 

代码隐藏

public MainWindow() 
{ 
    InitializeComponent(); 

    this.DataContext = new TabsViewModel(); 
} 

XAML

这是最漂亮的东西。我是无法到:

  1. 创建正常的层级嵌套TabControls。
  2. 连接他们的IsSelected和绑定项IsSelected在数据类型中。

所以,现在我只能建议通过硬编码的TabItems以下XAML:

<Grid> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition/> 
     <ColumnDefinition/> 
    </Grid.ColumnDefinitions> 
    <TreeView Grid.Row="0" Grid.Column="0" 
       ItemsSource="{Binding Items}"> 
     <blend:Interaction.Behaviors> 
      <view:BindableSelectedItemBehavior SelectedItem="{Binding SelectedItem, Mode=TwoWay}" /> 
     </blend:Interaction.Behaviors> 
     <TreeView.Resources> 
      <DataTemplate x:Key="tabItemTemplateLeaf"> 
       <StackPanel Orientation="Horizontal"> 
        <TextBlock Text="{Binding Name}"/> 
       </StackPanel> 
      </DataTemplate> 
      <HierarchicalDataTemplate x:Key="tabItemTemplate" 
             ItemTemplate="{StaticResource tabItemTemplateLeaf}" ItemsSource="{Binding Children}"> 
       <StackPanel Orientation="Horizontal"> 
        <TextBlock Text="{Binding Name}"/> 
       </StackPanel> 
      </HierarchicalDataTemplate> 
     </TreeView.Resources> 
     <TreeView.ItemTemplate> 
      <StaticResource ResourceKey="tabItemTemplate"/> 
     </TreeView.ItemTemplate>    
    </TreeView> 
    <TabControl Grid.Row="0" Grid.Column="1"> 
     <TabItem DataContext="{Binding Items[0]}" Header="{Binding Name}" IsSelected="{Binding IsSelected}"> 
      <TabControl> 
       <TabItem DataContext="{Binding Children[0]}" Header="{Binding Name}" IsSelected="{Binding IsSelected}"/> 
       <TabItem DataContext="{Binding Children[1]}" Header="{Binding Name}" IsSelected="{Binding IsSelected}"/> 
      </TabControl> 
     </TabItem> 
     <TabItem DataContext="{Binding Items[1]}" Header="{Binding Name}" IsSelected="{Binding IsSelected}"> 
      <TabControl> 
       <TabItem DataContext="{Binding Children[0]}" Header="{Binding Name}" IsSelected="{Binding IsSelected}"/> 
       <TabItem DataContext="{Binding Children[1]}" Header="{Binding Name}" IsSelected="{Binding IsSelected}"/> 
      </TabControl> 
     </TabItem> 
     <TabItem DataContext="{Binding Items[2]}" Header="{Binding Name}" IsSelected="{Binding IsSelected}"> 
      <TabControl> 
       <TabItem DataContext="{Binding Children[0]}" Header="{Binding Name}" IsSelected="{Binding IsSelected}"/> 
       <TabItem DataContext="{Binding Children[1]}" Header="{Binding Name}" IsSelected="{Binding IsSelected}"/> 
      </TabControl> 
     </TabItem> 
    </TabControl> 
</Grid> 

它采用混合行为类从this SO answer允许绑定到TreeView的SelectedItem属性(你将需要添加System.Windows.Interactions.dll到项目,并xmlns:blend="http://schemas.microsoft.com/expression/2010/interactivity"您XAML)

PS:我会尽量解决在XAML节中描述的问题,但现在它是我可以提出最好的。