首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >TabItem内容的样式

TabItem内容的样式
EN

Stack Overflow用户
提问于 2016-11-01 18:14:33
回答 1查看 1.7K关注 0票数 0

我有TabControl,它被用作我的应用程序的一个主要元素:

每个选项卡内容都有一个标题(与菜单名称重复)、分隔符和内容。必须与此视图相对应的XAML代码应该如下所示:

代码语言:javascript
复制
<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用于此:

代码语言:javascript
复制
<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的头部。

我试图为此使用RelativeSource,但这是行不通的:

代码语言:javascript
复制
<Label FontSize="20" Content="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabItem}}, Path=Header}"/>
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-11-01 18:26:32

如果我理解正确的话,你就很接近了--你只是想给它一个ContentTemplate,而不是用样式设置Content

代码语言:javascript
复制
<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>

现在,关于标签内容。您不能通过RelativeSource AncestorType获得这一点,因为TabItem不在可视树中:如果您编写了一个VisualTreeHelper.GetParent()循环,您会发现父链碰到了一些随机的东西,比如网格之类的东西,然后突然出现在TabControl上。

所以我们要做的是写一个多值转换器。我们给它DataContext表示DataTemplate --这是TabItem it的Content -和TabControl。然后,我们通过TabControlItems查找具有相同ContentTabItem

我尝试作为一个常规的值转换器,只从Label传入Label,在转换器内的可视树中遍历以找到TabControl,并使用转换器内的Label's DataContext来识别我想要的TabItem。这是因为(我认为)虚拟化没有起作用:DataTemplate被实例化一次,这些控件被重用。因为每次{RelativeSource Self}的值都是相同的,而且我没有告诉Binding关于DataContext的任何事情,所以值转换器只对被选中的第一个TabItem调用。多值转换器通过显式绑定到. ( DataContext )来解决这个问题.

如果使用ItemsSource填充TabControl,这种情况就会中断。事实上,如果您在TabControl中填充了TabItems以外的任何内容,它就会中断,就像您做的那样。但是,您不可能以其他方式设置它们的Header属性,如果您使用的是ItemsSource,那么您将有各种各样的好东西要绑定,而且您也不会考虑像这样的疯狂的权宜之计。

TabItemHeaderConverter.cs

代码语言:javascript
复制
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();
    }
}

新的XAML:

代码语言:javascript
复制
<Style x:Key="MyCustomStyle" TargetType="{x:Type TabControl}">
    <Style.Resources>
        <local:TabItemHeaderConverter x:Key="TabItemHeaderConverter" />

        <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" 
                                >
                                <Label.Content>
                                    <MultiBinding Converter="{StaticResource TabItemHeaderConverter}">
                                        <Binding RelativeSource="{RelativeSource AncestorType=TabControl}" />
                                        <Binding Path="." />
                                    </MultiBinding>
                                </Label.Content>
                            </Label>
                            <Separator />
                            <ContentControl 
                                Content="{Binding}"
                            />
                        </StackPanel>
                    </DataTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Style.Resources>
    <Setter Property="TabStripPlacement" Value="Left"/>
</Style>
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40366090

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档