WPF TabItem 标题模板

2024-05-05

示例代码:

 <TabControl>
    <TabItem>
        <TabItem.Header>
            <StackPanel Orientation="Horizontal" Margin="5">
                <Image Source="/WpfTutorialSamples;component/Images/bullet_blue.png" />
                <TextBlock Text="Blue" Foreground="Blue" />
            </StackPanel>
        </TabItem.Header>
        <Label Content="Content goes here..." />
    </TabItem>
    <TabItem>
        <TabItem.Header>
            <StackPanel Orientation="Horizontal" Margin="5">
                <TextBlock Text="Red" Foreground="Red" />
            </StackPanel>
        </TabItem.Header>
    </TabItem>
    <TabItem>
        <TabItem.Header>
            <StackPanel Orientation="Horizontal" Margin="5">
                <Rectangle Fill="Red" width="20" height="16" />
            </StackPanel>
        </TabItem.Header>
    </TabItem>
</TabControl>

正如您所看到的,TabItem 标题始终是具有不同内容的堆栈面板:

<TabItem.Header>
    <StackPanel Orientation="Horizontal" Margin="5">

    </StackPanel>
</TabItem.Header>

如何将其放入模板中,以便我没有重复的堆栈面板代码?

尝试这样做:

<TabControl>
    <TabControl.Resources>
        <Style TargetType="TabItem">
        <Setter Property="HeaderTemplate">
            <Setter.Value>
            <DataTemplate>
            <StackPanel Orientation="Horizontal" Margin="5">
                <ContentPresenter Content="{TemplateBinding ContentControl.Content}"
                            ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}"  
                            ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}" 
                            HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}" 
                            RecognizesAccessKey="True" 
                            SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}"  
                            VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}">
                </ContentPresenter>
            </StackPanel>
            </DataTemplate>
            </Setter.Value>
        </Setter>
        </Style>
    </TabControl.Resources>
    <TabItem>
        <TabItem.Header>
            <!-- ??? -->
            <TextBlock Text="X" />
            <TextBlock Text="Y" />
        </TabItem.Header>
</TabControl>

结果是:

  • “属性‘标题’被设置多次。”
  • “对象‘Object’已经有一个子对象,无法添加‘TextBlock’。‘Object’只能接受一个子对象。”

树标题唯一真正的共同点是 Margin="5"。在第二个和第三个选项卡中,堆栈面板是无关的,因为它只有一个子级。您可以使用 HeaderTemplate 或 ItemContainerStyle 来实现它:

<TabControl>
    <TabControl.ItemContainerStyle>
        <Style TargetType="TabItem">
            <Setter Property="Padding" Value="5" />
        </Style>
    </TabControl.ItemContainerStyle>

    <TabItem>
        <TabItem.Header>
            <StackPanel Orientation="Horizontal">
                <Image Source="/WpfTutorialSamples;component/Images/bullet_blue.png" />
                <TextBlock Text="Blue" Foreground="Blue" />
            </StackPanel>
        </TabItem.Header>
        <Label Content="Content goes here..." />
    </TabItem>
    <TabItem>
        <TabItem.Header>
            <TextBlock Text="Red" Foreground="Red" />
        </TabItem.Header>
    </TabItem>
    <TabItem>
        <TabItem.Header>
            <Rectangle Fill="Red" Width="20" Height="16" />
        </TabItem.Header>
    </TabItem>
</TabControl>

现在你不再重复任何事情。

您还可以将 stackpanel 的属性提取到样式以避免重复:

    <TabItem.Header>
        <StackPanel Style="{StaticResource TabHeaderPanel}">
            <Image Source="/WpfTutorialSamples;component/Images/bullet_blue.png" />
            <TextBlock Text="Blue" Foreground="Blue" />
        </StackPanel>
    </TabItem.Header>

    <TabItem.Header>
        <StackPanel Style="{StaticResource TabHeaderPanel}">
            <TextBlock Text="Red" Foreground="Red" />
        </StackPanel>
    </TabItem.Header>

    <TabItem.Header>
        <StackPanel Style="{StaticResource TabHeaderPanel}">
            <Rectangle Fill="Red" width="20" height="16" />
        </StackPanel>
    </TabItem.Header>

如果您想要更多的代码重用,您应该考虑类似 MVVM 的方法:

<TabControl ItemsSource="{Binding Tabs}">
    <TabControl.ItemContainerStyle>
        <Style TargetType="TabItem">
            <Setter Property="HeaderTemplate">
                <Setter.Value>
                    <DataTemplate DataType="local:TabViewModel">

                        <StackPanel Orientation="Horizontal" Margin="5">
                            <Image x:Name="Icon" Source="{Binding Icon, Converter={StaticResource UriToBitmapSourceConverter}}" />
                            <Rectangle x:Name="ColorRect" Height="16" Width="16" Fill="{Binding Color}" Visibility="Collapsed" />
                            <TextBlock Text="{Binding Title}" Foreground="{Binding Color}"/>
                        </StackPanel>

                        <DataTemplate.Triggers>
                            <DataTrigger Binding="{Binding Icon}" Value="{x:Null}">
                                <Setter TargetName="Icon" Property="Visibility" Value="Collapsed" />
                                <Setter TargetName="ColorRect" Property="Visibility" Value="Visible" />
                            </DataTrigger>
                        </DataTemplate.Triggers>
                    </DataTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </TabControl.ItemContainerStyle>
</TabControl>

如果您不能对所有标头使用单个 DataTemplate,您可以使用HeaderTemplateSelector

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

WPF TabItem 标题模板 的相关文章

  • 如何从 C# 中的 dataTable.Select( ) 查询中删除单引号?

    所以我有一个经销商名称列表 我正在我的数据表中搜索它们 问题是 一些傻瓜必须被命名为 Young s 这会导致错误 drs dtDealers Select DealerName dealerName 所以我尝试替换字符串 尽管它对我不起作
  • 适合初学者的良好调试器教程[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 有谁知道一个好的初学者教程 在 C 中使用调试器 我感觉自己好像错过了很多 我知道怎么做 单步执行代码并查看局部变量 虽然这常常给我带来问
  • 使用 C# 登录《我的世界》

    我正在尝试为自己和一些朋友创建一个简单的自定义 Minecraft 启动器 我不需要启动 Minecraft 的代码 只需要登录的实际代码行 例如 据我所知 您过去可以使用 string netResponse httpGET https
  • 为什么pow函数比简单运算慢?

    从我的一个朋友那里 我听说 pow 函数比简单地将底数乘以它的指数的等价函数要慢 例如 据他介绍 include
  • IdentityServer 4 对它的工作原理感到困惑

    我阅读和观看了很多有关 Identity Server 4 的内容 但我仍然对它有点困惑 因为似乎有很多移动部件 我现在明白这是一个单独的项目 它处理用户身份验证 我仍然不明白的是用户如何注册它 谁存储用户名 密码 我打算进行此设置 Rea
  • XAML 构建的本地 TFS 到 VSTS 迁移

    目前 我们在本地使用 TFS 2017 update 1 但我们必须在 VSTS 云平台上迁移 TFS 此外 我们还使用自定义构建模板在本地使用 TFS 构建服务器进行 XAML 构建 我们的问题是迁移后所有 XAML 构建定义是否都能正常
  • JNI 将 Char* 2D 数组传递给 JAVA 代码

    我想从 C 代码通过 JNI 层传递以下指针数组 char result MAXTEST MAXRESPONSE 12 12 8 3 29 70 5 2 42 42 在java代码中我写了以下声明 public static native
  • 当一组凭据下的计划任务启动的进程在另一组凭据下运行另一个程序时,Windows 是否有限制

    所以我有一个简单的例子 其中我有应用程序 A 它对用户 X 本地管理员 有一些硬编码的凭据 然后它使用硬编码的绝对路径启动带有这些凭据的应用程序 B A 和 B 以及 dotnet 控制台应用程序 但是它们不与控制台交互 只是将信息写入文件
  • C# 数据表更新多行

    我如何使用数据表进行多次更新 我找到了这个更新 1 行 http support microsoft com kb 307587 my code public void ExportCSV string SQLSyntax string L
  • 使用可变参数包类型扩展的 C++ 函数调用者包装器

    我绑定了一些 API 并且绑定了一些函数签名 如下所示 static bool WrapperFunction JSContext cx unsigned argc JS Value vp 我尝试将对象和函数包装在 SpiderMonkey
  • File.AppendText 尝试写入错误的位置

    我有一个 C 控制台应用程序 它作为 Windows 任务计划程序中的计划任务运行 此控制台应用程序写入日志文件 该日志文件在调试模式下运行时会创建并写入应用程序文件夹本身内的文件 但是 当它在任务计划程序中运行时 它会抛出一个错误 指出访
  • 在Linux中,找不到框架“.NETFramework,Version=v4.5”的参考程序集

    我已经设置了 Visual studio 来在我的 Ubuntu 机器上编译 C 代码 我将工作区 我的代码加载到 VS 我可以看到以下错误 The reference assemblies for framework NETFramewo
  • 告诉 Nancy 将枚举序列化为字符串

    Nancy 默认情况下在生成 JSON 响应时将枚举序列化为整数 我需要将枚举序列化为字符串 有一种方法可以通过创建来自定义 Nancy 的 JSON 序列化JavaScript 原始转换器 https github com NancyFx
  • 为什么可以通过ref参数修改readonly字段?

    考虑 class Foo private readonly string value public Foo Bar ref value private void Bar ref string value value hello world
  • C# 存档中的文件列表

    我正在创建一个 FileFinder 类 您可以在其中进行如下搜索 var fileFinder new FileFinder new string C MyFolder1 C MyFolder2 new string
  • 打破 ReadFile() 阻塞 - 命名管道 (Windows API)

    为了简化 这是一种命名管道服务器正在等待命名管道客户端写入管道的情况 使用 WriteFile 阻塞的 Windows API 是 ReadFile 服务器已创建启用阻塞的同步管道 无重叠 I O 客户端已连接 现在服务器正在等待一些数据
  • 在视口中查找 WPF 控件

    Updated 这可能是一个简单或复杂的问题 但在 wpf 中 我有一个列表框 我用一个填充数据模板从列表中 有没有办法找出特定的数据模板项位于视口中 即我已滚动到其位置并且可以查看 目前我连接到了 listbox ScrollChange
  • 为什么我的单选按钮不起作用?

    我正在 Visual C 2005 中开发 MFC 对话框应用程序 我的单选按钮是 m Small m Medium 和 m Large 它们都没有在我的 m Summary 编辑框中显示应有的内容 可能出什么问题了 这是我的代码 Pizz
  • Unity:通过拦截将两个接口注册为一个单例

    我有一个实现两个接口的类 我想对该类的方法应用拦截 我正在遵循中的建议Unity 将两个接口注册为一个单例 https stackoverflow com questions 1394650 unity register two inter
  • 如何使用 C++11 using 语法键入定义函数指针?

    我想写这个 typedef void FunctionPtr using using 我该怎么做呢 它具有类似的语法 只不过您从指针中删除了标识符 using FunctionPtr void 这是一个Example http ideone

随机推荐