我正在构建一个设置窗口,左侧有TreeView
,右侧有TabControl
- 布局基于Microsoft Visual Studio选项对话框。
TabControl
有3 TabItems
,因此有3个标签。每个TabItems
都包含一个TabControl
,其中包含2个TabItems
。我计划稍后隐藏TabControl
标签,但回到TreeView
,它将如下所示:
在我的XAML中,一切都在视觉上正常。我正试图弄清楚这个代码隐藏。
我想拥有它,因此点击TreeView
中的项目会导致相应的TabItem
生效。如何获取Treeview
所选项目/节点并导致所有TabControls
做出反应?
我在质疑这是否是最佳方式。我必须维护TreeView
项和TabControl
TabItems
...
答案 0 :(得分: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;
}
我们需要一些主视图模型:
代码:
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();
}
这是最不美好的事情。我无法两者:
所以,现在我只能提出以下带有硬编码tabItem的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中
P.S:我将尝试解决XAML部分中描述的问题,但是现在它是我能提出的最好的问题。