每个标签内容都有标题(与菜单名称重复),分隔符和内容。我必须与此视图对应的XAML代码应如下所示:
<TabControl Style="{StaticResource MyCustomStyle}">
<TabItem Header="Menu 1">
<TabItem.Content>
...
</TabItem.Content>
</TabItem>
<TabItem Header="Menu 2">
<TabItem.Content>
<TextBlock>Content</TextBlock>
</TabItem.Content>
</TabItem>
...
</TabControl>
为避免重复部分代码,我决定以自定义样式设置视图。
MyCustomStyle
为此:
<Style x:Key="MyCustomStyle" TargetType="{x:Type TabControl}">
<Style.Resources>
<Style TargetType="{x:Type TabItem}">
<Setter Property="Padding" Value="10"/>
<Setter Property="Width" Value="120"/>
<Setter Property="Content">
<Setter.Value>
<StackPanel Margin="10">
<Label FontSize="20" Content="..."/>
<Separator/>
<ContentPresenter ContentSource="..."/>
</StackPanel>
</Setter.Value>
</Setter>
</Style>
</Style.Resources>
<Setter Property="TabStripPlacement" Value="Left"/>
</Style>
修改内容时出现唯一的问题。标签不希望将值绑定到TabItem
标头。 ContentPresenter
我尝试使用RelativeSource
,但这不起作用:
<Label FontSize="20" Content="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabItem}}, Path=Header}"/>
答案 0 :(得分:2)
如果我理解正确,你就非常接近 - 你只想给它一个ContentTemplate
,而不是在风格中设置Content
:
<Style x:Key="MyCustomStyle" TargetType="{x:Type TabControl}">
<Style.Resources>
<Style TargetType="{x:Type TabItem}">
<Setter Property="Padding" Value="10"/>
<Setter Property="Width" Value="120"/>
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Margin="10">
<Label FontSize="20" Content="..."/>
<Separator/>
<ContentControl
Content="{Binding}"
/>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</Style.Resources>
<Setter Property="TabStripPlacement" Value="Left"/>
</Style>
现在,对于Label内容。你不能通过RelativeSource AncestorType
得到它,因为TabItem
不在可视化树中:如果你写了一个VisualTreeHelper.GetParent()
循环,你会发现父链碰到一堆随机的东西,比如网格等等,然后突然出现在TabControl
上。
所以我们做的是,我们编写一个多值转换器。我们为DataContext
提供DataTemplate
- Content
为TabItem
为ContentTemplated - 和TabControl
。然后,我们会查看TabControl
的{{1}},找到具有相同Items
的{{1}}。
我尝试将其作为常规值转换器,只需从TabItem
传入Content
,在转换器内部移动可视树以找到{RelativeSource Self}
,然后使用Label
在转换器内部TabControl
标识我想要的Label
。由于(我认为)虚拟化,这不起作用:DataContext
被实例化一次,并且这些控件被重用。由于TabItem
的值每次都相同,而我没有告诉DataTemplate
有关{RelativeSource Self}
的任何内容,因此仅为第一个Binding
调用了值转换器曾被选中。多值转换器通过显式绑定到DataContext
TabItem
来解决该问题。
如果您使用.
填充DataContext
,则会中断此操作。事实上,如果你像ItemsSource
那样用TabControl
填充TabControl
,就会破坏它。但是,你不能设置他们的TabItems
属性,如果你使用Header
,你就会有各种各样的好东西要绑定,你不会考虑坚果的权宜之计像这个。
TabItemHeaderConverter.cs
ItemsSource
新的XAML:
public class TabItemHeaderConverter : IMultiValueConverter
{
// This is pretty awful, but nobody promised life would be perfect.
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
var tc = values[0] as TabControl;
var tabItemContent = values[1];
var tabItem = tc.Items.Cast<TabItem>().FirstOrDefault(ti => ti.Content == tabItemContent);
if (null != tabItem)
{
return tabItem.Header;
}
return "Unknown";
}
public object[] ConvertBack(object value, Type[] targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}