2015-05-08 60 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節中描述的問題,但現在它是我可以提出最好的。