WPF TabControl 滚动选项卡

2024-03-05 05:28

本文主要是介绍WPF TabControl 滚动选项卡,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 前言
  • 相关链接
  • TabControl是什么东西
    • 通过模板副本查看样式
    • IsItemsHost
    • 如何修改
    • HandyControl的TabControl 滚动
  • 总结

前言

我原本以为是很简单的事情,但是没想到实际做起来还是有很多的基础知识点的。

相关链接

WPF 控件库——可拖动选项卡的TabControl

TabControl是什么东西

我们平常写TabControl的时候,可能都很习惯了直接写TabControl+TabItem。但是TabControl负责了什么布局,TabItem负责了什么布局,我们都不知道。

在《深入浅出WPF》中,我们可以看到TabControl属于ItemsControl

在这里插入图片描述

通过模板副本查看样式

我们去看看控件模板样式副本。WPF的xaml的优点是每个控件都是单独的逻辑,耦合低。缺点是写起来麻烦,每次改动约等于重新写一个新的。通过增加自己的工作量来降低了耦合

在这里插入图片描述

    <SolidColorBrush x:Key="TabItem.Selected.Background" Color="#FFFFFF"/><SolidColorBrush x:Key="TabItem.Selected.Border" Color="#ACACAC"/><Style x:Key="TabControlStyle1" TargetType="{x:Type TabControl}"><!--默认基础属性--><Setter Property="Padding" Value="2"/><Setter Property="HorizontalContentAlignment" Value="Center"/><Setter Property="VerticalContentAlignment" Value="Center"/><Setter Property="Background" Value="{StaticResource TabItem.Selected.Background}"/><Setter Property="BorderBrush" Value="{StaticResource TabItem.Selected.Border}"/><Setter Property="BorderThickness" Value="1"/><Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/><!--控件模板--><Setter Property="Template"><Setter.Value><!--选择控件模板属性模板--><ControlTemplate TargetType="{x:Type TabControl}"><Grid x:Name="templateRoot" ClipToBounds="true" SnapsToDevicePixels="true" KeyboardNavigation.TabNavigation="Local"><Grid.ColumnDefinitions><ColumnDefinition x:Name="ColumnDefinition0"/><ColumnDefinition x:Name="ColumnDefinition1" Width="0"/></Grid.ColumnDefinitions><Grid.RowDefinitions><RowDefinition x:Name="RowDefinition0" Height="Auto"/><RowDefinition x:Name="RowDefinition1" Height="*"/></Grid.RowDefinitions><!--设置TabItem选项卡的布局--><TabPanel x:Name="headerPanel" Background="Transparent" Grid.Column="0" IsItemsHost="true" Margin="2,2,2,0" Grid.Row="0" KeyboardNavigation.TabIndex="1" Panel.ZIndex="1"/><!--设置TabItem的内容--><Border x:Name="contentPanel" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Grid.Column="0" KeyboardNavigation.DirectionalNavigation="Contained" Grid.Row="1" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local"><ContentPresenter x:Name="PART_SelectedContentHost" ContentSource="SelectedContent" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/></Border></Grid><!--用于设置位置布局--><ControlTemplate.Triggers><Trigger Property="TabStripPlacement" Value="Bottom"><Setter Property="Grid.Row" TargetName="headerPanel" Value="1"/><Setter Property="Grid.Row" TargetName="contentPanel" Value="0"/><Setter Property="Height" TargetName="RowDefinition0" Value="*"/><Setter Property="Height" TargetName="RowDefinition1" Value="Auto"/><Setter Property="Margin" TargetName="headerPanel" Value="2,0,2,2"/></Trigger><Trigger Property="TabStripPlacement" Value="Left"><Setter Property="Grid.Row" TargetName="headerPanel" Value="0"/><Setter Property="Grid.Row" TargetName="contentPanel" Value="0"/><Setter Property="Grid.Column" TargetName="headerPanel" Value="0"/><Setter Property="Grid.Column" TargetName="contentPanel" Value="1"/><Setter Property="Width" TargetName="ColumnDefinition0" Value="Auto"/><Setter Property="Width" TargetName="ColumnDefinition1" Value="*"/><Setter Property="Height" TargetName="RowDefinition0" Value="*"/><Setter Property="Height" TargetName="RowDefinition1" Value="0"/><Setter Property="Margin" TargetName="headerPanel" Value="2,2,0,2"/></Trigger><Trigger Property="TabStripPlacement" Value="Right"><Setter Property="Grid.Row" TargetName="headerPanel" Value="0"/><Setter Property="Grid.Row" TargetName="contentPanel" Value="0"/><Setter Property="Grid.Column" TargetName="headerPanel" Value="1"/><Setter Property="Grid.Column" TargetName="contentPanel" Value="0"/><Setter Property="Width" TargetName="ColumnDefinition0" Value="*"/><Setter Property="Width" TargetName="ColumnDefinition1" Value="Auto"/><Setter Property="Height" TargetName="RowDefinition0" Value="*"/><Setter Property="Height" TargetName="RowDefinition1" Value="0"/><Setter Property="Margin" TargetName="headerPanel" Value="0,2,2,2"/></Trigger><Trigger Property="IsEnabled" Value="false"><Setter Property="TextElement.Foreground" TargetName="templateRoot" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style>

我们可以看到中间有个Gird分布,用于声明选项卡和内容之间布局关系。那么哪个代表选项卡,哪个代码【内容】呢?

在这里插入图片描述

IsItemsHost

其实选项卡布局还有一个要求,就是得声明【IsItemsHost】这个属性,我们可以看看微软官方文档是怎么说的。

Panel.IsItemsHost 属性

在这里插入图片描述

简单来说【IsItemsHost】就是一个可以自动绑定的ItemPanel的声明,ItemPanel是设置ItemControl的布局方式。

如何修改

其实改起来很简单,就是加个【ScrollViewer】就行了。原来的是Panel,我们改成StackPanel这样就不会自动换行了。

<Window x:Class="WpfApp2.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WpfApp2"mc:Ignorable="d"Title="MainWindow"Height="450"Width="800"><Window.Resources><SolidColorBrush x:Key="TabItem.Selected.Background"Color="#FFFFFF" /><SolidColorBrush x:Key="TabItem.Selected.Border"Color="#ACACAC" /><Style x:Key="TabControlStyle1"TargetType="{x:Type TabControl}"><!--默认基础属性--><Setter Property="Padding"Value="2" /><Setter Property="HorizontalContentAlignment"Value="Center" /><Setter Property="VerticalContentAlignment"Value="Center" /><Setter Property="Background"Value="{StaticResource TabItem.Selected.Background}" /><Setter Property="BorderBrush"Value="{StaticResource TabItem.Selected.Border}" /><Setter Property="BorderThickness"Value="1" /><Setter Property="Foreground"Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" /><!--控件模板--><Setter Property="Template"><Setter.Value><!--选择控件模板属性模板--><ControlTemplate TargetType="{x:Type TabControl}"><Grid x:Name="templateRoot"ClipToBounds="true"SnapsToDevicePixels="true"KeyboardNavigation.TabNavigation="Local"><Grid.ColumnDefinitions><ColumnDefinition x:Name="ColumnDefinition0" /><ColumnDefinition x:Name="ColumnDefinition1"Width="0" /></Grid.ColumnDefinitions><Grid.RowDefinitions><RowDefinition x:Name="RowDefinition0"Height="Auto" /><RowDefinition x:Name="RowDefinition1"Height="*" /></Grid.RowDefinitions><!--设置TabItem选项卡的布局--><ScrollViewer Height="{TemplateBinding Height}" ><StackPanel x:Name="headerPanel"Background="Transparent"Grid.Column="0"IsItemsHost="True"Margin="2,2,2,0"Grid.Row="0"KeyboardNavigation.TabIndex="1"Panel.ZIndex="1" /></ScrollViewer><!--设置TabItem的内容--><Border x:Name="contentPanel"Background="{TemplateBinding Background}"BorderBrush="{TemplateBinding BorderBrush}"BorderThickness="{TemplateBinding BorderThickness}"Grid.Column="0"KeyboardNavigation.DirectionalNavigation="Contained"Grid.Row="1"KeyboardNavigation.TabIndex="2"KeyboardNavigation.TabNavigation="Local"><ContentPresenter x:Name="PART_SelectedContentHost"ContentSource="SelectedContent"Margin="{TemplateBinding Padding}"SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" /></Border></Grid><!--用于设置位置布局--><ControlTemplate.Triggers><Trigger Property="TabStripPlacement"Value="Bottom"><Setter Property="Grid.Row"TargetName="headerPanel"Value="1" /><Setter Property="Grid.Row"TargetName="contentPanel"Value="0" /><Setter Property="Height"TargetName="RowDefinition0"Value="*" /><Setter Property="Height"TargetName="RowDefinition1"Value="Auto" /><Setter Property="Margin"TargetName="headerPanel"Value="2,0,2,2" /></Trigger><Trigger Property="TabStripPlacement"Value="Left"><Setter Property="Grid.Row"TargetName="headerPanel"Value="0" /><Setter Property="Grid.Row"TargetName="contentPanel"Value="0" /><Setter Property="Grid.Column"TargetName="headerPanel"Value="0" /><Setter Property="Grid.Column"TargetName="contentPanel"Value="1" /><Setter Property="Width"TargetName="ColumnDefinition0"Value="Auto" /><Setter Property="Width"TargetName="ColumnDefinition1"Value="*" /><Setter Property="Height"TargetName="RowDefinition0"Value="*" /><Setter Property="Height"TargetName="RowDefinition1"Value="0" /><Setter Property="Margin"TargetName="headerPanel"Value="2,2,0,2" /></Trigger><Trigger Property="TabStripPlacement"Value="Right"><Setter Property="Grid.Row"TargetName="headerPanel"Value="0" /><Setter Property="Grid.Row"TargetName="contentPanel"Value="0" /><Setter Property="Grid.Column"TargetName="headerPanel"Value="1" /><Setter Property="Grid.Column"TargetName="contentPanel"Value="0" /><Setter Property="Width"TargetName="ColumnDefinition0"Value="*" /><Setter Property="Width"TargetName="ColumnDefinition1"Value="Auto" /><Setter Property="Height"TargetName="RowDefinition0"Value="*" /><Setter Property="Height"TargetName="RowDefinition1"Value="0" /><Setter Property="Margin"TargetName="headerPanel"Value="0,2,2,2" /></Trigger><Trigger Property="IsEnabled"Value="false"><Setter Property="TextElement.Foreground"TargetName="templateRoot"Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" /></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style><Style TargetType="TabItem"x:Key="default"><Setter Property="FontSize"Value="50" /></Style></Window.Resources><Grid><TabControl Style="{DynamicResource TabControlStyle1}" TabStripPlacement="Left"><TabItem Header="标题1"Style="{StaticResource default}"></TabItem><TabItem Header="标题2"Style="{StaticResource default}"></TabItem><TabItem Header="标题3"Style="{StaticResource default}"></TabItem><TabItem Header="标题4"Style="{StaticResource default}"></TabItem><TabItem Header="标题5"Style="{StaticResource default}"></TabItem><TabItem Header="标题6"Style="{StaticResource default}"></TabItem><TabItem Header="标题7"Style="{StaticResource default}"></TabItem><TabItem Header="标题8"Style="{StaticResource default}"></TabItem></TabControl></Grid>
</Window>

在这里插入图片描述

HandyControl的TabControl 滚动

我们看看HandyControl的代码

在这里插入图片描述
我们进到代码里面,可以看到他实现了ContentControl,这里我们就不展开说明了

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

总结

控件模板是必须要深入了解的。WPF我认为就3+1个难点。控件模板,依赖属性,Binding+WPF 动画。前三个掌握了,基本的静态页面就可以写了。动画属于附加需求,不用动画也可以写的很好看

这篇关于WPF TabControl 滚动选项卡的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/775447

相关文章

html css jquery选项卡 代码练习小项目

在学习 html 和 css jquery 结合使用的时候 做好是能尝试做一些简单的小功能,来提高自己的 逻辑能力,熟悉代码的编写语法 下面分享一段代码 使用html css jquery选项卡 代码练习 <div class="box"><dl class="tab"><dd class="active">手机</dd><dd>家电</dd><dd>服装</dd><dd>数码</dd><dd

UniApp实现漂亮的音乐歌词滚动播放效果

在现代的音乐播放应用中,歌词的展示和滚动播放已经成为了一个非常常见的功能。今天,我们将通过UniApp来实现一个漂亮的歌词滚动播放功能。我们将使用UniApp提供的组件和API来完成这个任务。 页面结构 在页面的模板部分,我们需要创建一个音频播放器和歌词展示区域。使用<scroll-view>组件来实现歌词的滚动效果。 <template><view class="audio-co

选项卡制作问题--折磨了我一整天,记录下来

看老曹的html+css课程,学习html+css基础,讲到制作选项卡,以京东商城的选项卡为例,效果如下: 看着他做出来很简单,结果自己做花了2个多小时才有个样子,效果是这样的: 内部代码如下 <!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-

WPF入门到跪下 第十三章 3D绘图 - 3D绘图基础

3D绘图基础 四大要点 WPF中的3D绘图涉及4个要点: 视口,用来驻留3D内容3D对象照亮部分或整个3D场景的光源摄像机,提供在3D场景中进行观察的视点 一、视口 要展示3D内容,首先需要一个容器来装载3D内容。在WPF中,这个容器就是Viewport3D(3D视口),它继承自FrameworkElement,因此可以像其他元素那样在XAML中使用。 Viewport3D与其他元素相

【Unity-Lua】音乐播放器循环滚动播放音乐名

前言:Unity中UI节点 图1 如上所示,一开始本来是打算用ScrollView做的,觉得直接计算对应的文本位置就行,所以没用ScrollRect来做,可以忽略Scroll,Viewport这些名字。如下图:需要在一个背景Image组件上添加上Mask组件来显示固定位置的文本显示。 图2 图3 并且需要在要显示的文本上挂载Content Size Filter组件,但是这儿会有个坑

WebAPI(二)、DOM事件监听、事件对象event、事件流、事件委托、页面加载与滚动事件、页面尺寸事件

文章目录 一、 DOM事件1. 事件监听2. 事件类型(1)、鼠标事件(2)、焦点事件(3)、键盘事件(4)、文本事件 3. 事件对象(1)、获取事件对象(2)、事件对象常用属性 4. 环境对象 this5. 回调函数 二、 DOM事件进阶1. 事件流(1)、 捕获阶段(2)、 冒泡阶段(3)、 阻止冒泡(4) 、阻止元素默认行为(5) 、解绑事件 2. 事件委托3. 其他事件(1)、页面加

【Android】NestedScrollView的简单用法与滚动冲突、滑动冲突

一、NestedScrollView 1. 什么是 NestedScrollView NestedScrollView 是 Android 中一个用于处理垂直方向滚动的布局组件,它继承自 FrameLayout,同时支持嵌套滑动(Nested Scrolling)机制。相比于传统的 ScrollView,NestedScrollView 专为解决嵌套滚动冲突问题设计,能够与其他支持嵌套滑动的子

C# WPF燃气报警器记录读取串口工具

C# WPF燃气报警器记录读取串口工具 概要串口帧数据布局文件代码文件运行效果源码下载 概要 符合国标文件《GB+15322.2-2019.pdf》串口通信协议定义;可读取燃气报警器家用版设备历史记录信息等信息; 串口帧数据 串口通信如何确定一帧数据接收完成是个麻烦事,本文采用最后一次数据接收完成后再过多少毫秒认为一帧数据接收完成,开始解析出来。每次接收到数据更新一次re

Jquery实现广告滚动

当页面的滚动条上下移动时,飘浮广告随着滚动条的滚动而上移或者下移,要明白两点,第一:放广告的层最好采用绝对定位,它的位置应该随着滚动条的改变而上下移动,滚动条的滚动促发的是onscroll事件,广告条所在的层的top值就是滚动条的高度,具体代码如下: <html><head><meta http-equiv="Content-Type" content="text/html; charset

滚动偏移量 scroll offset

滚动偏移量 scroll offset 一、获取滚动偏移量二、滚动事件性能三、使用场景 滚动偏移量(scroll offset):文档在垂直和水平方向上滚动的距离 一、获取滚动偏移量 // 获取上下滚动偏移量const scrollTop = window.pageYOffset || document.documentElement.scrollTop || docu