WPF自适应可关闭的TabControl 类似浏览器的标签页
效果如图:
虽然说是自适应可关闭的TabControl,但TabControl并不需要改动,不如叫自适应可关闭的TabItem.
大体思路:建一个用户控件,继承自TabItem,里面放个按钮,点击的时候在TabControl中移除自身.在添加,移除TabItem和TabControl尺寸变化时,通过Items的个数计算合适的Width.
新建用户控件
新建用户控件,并继承自TabItem,这样它就拥有TabItem所有的属性和事件.而这个功能不需要自定义依赖属性和事件.它的用法就和TabItem完全一样.
建完后把UserControl换成TabItem,去掉多余部分
后台继承自UserControl改成继承自TabItem
更改样式添加关闭按钮
在Xmal里添加一个自己喜欢的样式,最主要的是在Template里添加一个按钮,注册一个Click事件,用于关闭.
1 <Style TargetType="{x:Type TabItem}"> 2 <Setter Property="BorderBrush" Value="Black"></Setter> 3 <Setter Property="Background" Value="White"></Setter> 4 <Setter Property="Foreground" Value="Black"></Setter> 5 <Setter Property="Padding" Value="5,0,0,0"></Setter> 6 <Setter Property="HorizontalAlignment" Value="Left"></Setter> 7 <Setter Property="VerticalAlignment" Value="Center"></Setter> 8 <Setter Property="HorizontalContentAlignment" Value="Left"></Setter> 9 <Setter Property="VerticalContentAlignment" Value="Center"></Setter> 10 <Setter Property="Template"> 11 <Setter.Value> 12 <ControlTemplate TargetType="{x:Type TabItem}"> 13 <Border CornerRadius="5,0,0,0" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}"> 14 <Grid> 15 <Grid.ColumnDefinitions> 16 <ColumnDefinition Width="*"></ColumnDefinition> 17 <ColumnDefinition Width="20"></ColumnDefinition> 18 </Grid.ColumnDefinitions> 19 <ContentPresenter Grid.Column="0" ContentSource="Header" Margin="{TemplateBinding Padding}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"></ContentPresenter> 20 <Button Grid.Column="1" Name="btn_Close" Click="btn_Close_Click"></Button> 21 </Grid> 22 </Border> 23 <ControlTemplate.Triggers> 24 <Trigger Property="IsSelected" Value="true"> 25 <Setter Property="Background" Value="#FFFF923E"></Setter> 26 <Setter Property="Foreground" Value="White"></Setter> 27 </Trigger> 28 </ControlTemplate.Triggers> 29 </ControlTemplate> 30 </Setter.Value> 31 </Setter> 32 </Style>
View Code
后台的逻辑
查找父级TabControl
注意TabItem并不能关闭自身,这里所说的关闭其实是在他父级TabControl的Items集合里移除.而且父级TabControl的尺寸改变时还要注册事件去改变每个Item的Width.所以我决定找到它的父级TabControl,声明一个私有变量添加对父级的引用.
可以通过可视化树的帮助类VisualTreeHelper来找到它的父级TabControl.当然并不是它的父级直接就是TabControl了,需要递归去查找
1 /// <summary> 2 /// 递归找父级TabControl 3 /// </summary> 4 /// <param name="reference">依赖对象</param> 5 /// <returns>TabControl</returns> 6 private TabControl FindParentTabControl(DependencyObject reference) 7 { 8 DependencyObject dObj = VisualTreeHelper.GetParent(reference); 9 if (dObj == null) 10 return null; 11 if (dObj.GetType() == typeof(TabControl)) 12 return dObj as TabControl; 13 else 14 return FindParentTabControl(dObj); 15 }
View Code
计算尺寸
既然是自适应,总得有一个正常的尺寸,只有空间不足的时候才去缩小每个Item.我想到的最简单的办法就是做个约定,把这个尺寸放到父级TabControl的Tag里,这样可以通过对父级TabControl的引用,轻松拿到这个尺寸.
计算方法就是取父级TabControl运行时的宽度ActualWidth除以约定的尺寸,取整形int,这个就是保持约定宽度item个数的临界值了.
小于等于这个值就用约定宽度,大于这个值就用父级运行宽度除以Items的个数求出平均宽度,然后遍历父级TabControl的Items,都赋上这个平均值.
需要注意的是,如果所有Items的尺寸加起来大于等于父级的尺寸,Items会换行,感觉有点丑啊.所以我取的是父级运行宽度-5做的运算,这样就永远也抵达不到边界,不会换行.
不过也可以改写TabControl的控件模版,把放Hrader的容器换成Stackpanel就不会换行了,我只是觉得上面的方法比较简单.
父级尺寸改变
可以通过TabControl的SizeChanged事件监测到.需要干的事就是重新计算尺寸.
关闭按钮
在父级TabControl的Items集合里移除自身后,注意重新计算下尺寸和移除注册SizeChanged事件的方法.
最后附上代码 自适应可关闭的Tab.zip
这个效果比较常见,可能您已经做过了,有更好的想法希望您能分享出来,大家共同进步.
2016-08-16更新:感谢园友 日日夜夜 的反馈,源码已改正
1.TabItem.Resources的关闭按钮样式添加了Key,模版里的关闭按钮添加了对资源的引用.
2.去掉了TabItem样式的HorizontalContentAlignment="Left",VerticalContentAlignment="Center".头部内容的布局方式改为HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}".
WPF自适应可关闭的TabControl 类似浏览器的标签页相关推荐
- 实现浏览器多标签页通信
前言 我们都知道浏览器是可以打开很多标签页的,如果每个标签页代表的是单独的一个网站,那么这些标签页之间肯定是不能通信的,如果能通信那估计我们都得凉凉.但是在很多情况下,浏览器中的很多标签页都属于某一个 ...
- mac下chrome浏览器的标签页、进程和内存分配
因为最近要解决网页经常崩溃的问题,所以去研究了一下chrome浏览器的标签页和进程的关系,以及标签页对应进程的内存分配. 标签页和进程的对应关系 当chrome浏览器开启但是没有任何一个标签页的时候, ...
- ios开发跳转safari_阻止iOS Web APP中点击链接跳转到Safari 浏览器新标签页
最近为了更好地接触移动Web 开发狠心购买了一台ipad mini(之前一直都是借同学的,借多了就不好意思了).拿来调试DeveMobile 与EaseMobile 主题 时候发现了不少问题,现在在一 ...
- 前端如何设置浏览器网页标签页前的小图标favicon.ico
前端如何设置浏览器网页标签页前的小图标favicon.ico 步骤1: 将小图标favicon.ico文件(或者普通的icon小图片)放在项目的public或者static目录下 步骤2: index ...
- 在浏览器的标签页显示网站标志图标
一.在浏览器的标签页显示网站标志图标 我们通常希望将浏览器里的Tab选项卡的图标换成自己网站的logo图片,这样看起来更真实和有信任感,可以在<head></head>中添加l ...
- Chrome浏览器新标签页设置首页主页修改添加网站Infinity插件好用
Infinity new tab 是一款美观实用的chrome 新标签页.最常访问的网站添加,修改,删除网址都有,每日一图,云备份等功能都具备.是一款基于html5的Chrome扩展程序,它重新定义了 ...
- 浏览器新标签页设置失效解决办法
当我们使用identity或者itab标签页插件时,尽管浏览器已经设置启动时打开新标签页,但是重新打开浏览器会发现还是会没有进入我们使用的identity或者是itab新标签页,需要在标题点击'+'号 ...
- yandex禁止java script_Yandex最新版本浏览器新标签页按钮显示俄文的解决办法
最新的Yandex 20.11.3.179版本浏览器的语言包出现以下错误: 1.zh-CN.pak语言包里面有些俄文没有翻译完,中文"剪切"只翻译了"切".故重 ...
- 删除360浏览器新标签页内的热词导航
在360 浏览器的新标签页中,点击搜索栏经常弹出各种广告文字 为了删除这些内容,只要更改一下360浏览器安装根目录内的 newpages.zip 压缩包里 "new_page.html&qu ...
最新文章
- 回击质疑 HP StoreOnce用高性能说话
- windows域中时间同步的解决方案
- 手机号和邮箱正则匹配
- 【Python基础】Python安装第三方库太慢?配置好这个速度飞起
- Django框架(11.Django中的通过模型类查询数据以及相关函数和条件)
- BZOJ 2957 楼房重建-线段树
- Centos7 开启端口
- select的列子说明select内部实现原理
- 清华学霸直博简历:CPU、操作系统、编译器全自主写
- jQuery LigerUI 插件介绍及使用之ligerDrag和ligerResizable
- Netpas:不一样的SD-WAN+ 保障网络通讯品质
- UVA669 LA5662 Defragment【暴力】
- 标准I/O缓冲:全缓冲、行缓冲、无缓冲
- 3.4 小乌龟git使用说明
- 数据分享 — 国内外常用夜间灯光数据产品介绍
- [Qt]一个关于galgame的练手项目的总结
- 【PCIe总线】-- PCI、PCIE基础知识
- HTTP与HTTPS是什么?http和https的区别
- coreldraw2022直装版下载 永久免费使用 附安装教程( 仅限 win 10 用户 )
- Qt 小例子学习14 - 动态滚动QScrollArea
热门文章
- webuploader
- Oracel 格式化日期 to_char()
- C语言 scanf函数
- TC SRM 665 DIV2 B LuckyCycle 暴力
- 使用HttpURLConnection+AsyncTask访问webservice接口(返回json字符串)
- 浏览文件神器!且可以计算所有文件代码的行数!
- C# 概念 委托和事件
- A MULTI-TASK FRAMEWORK WITH FEATURE PASSING MODULE FOR SKIN LESION CLASSIFICATION AND SEGMENTATION
- 2.2 Mnist手写数据集
- sqoop增量导入hive_Sqoop 增量导MySQL数据 至Hive