news 2026/8/18 18:25:42

WPF实现可擦除的Tab标签页

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
WPF实现可擦除的Tab标签页
项目目标是展示如何在 WPF 应用中动态管理标签页,包括新增、关闭和切换标签页。
效果

该demo使用CommunityToolkit.Mvvm实现MVVM数据绑定与命令,通过Microsoft.Extensions.DependencyInjection配置 DI 容器,如要复刻需安装这两个包或自己实现INotifyPropertyChanged和ICommand

github地址:https://github.com/Edicius-Lia/WFPTabControl

MainWindow.xaml
<DockPanel> <Menu DockPanel.Dock="Top"> <MenuItem Header="文件"> <MenuItem Header="Page1" Command="{Binding OpenPage1Command}" /> <MenuItem Header="Page2" Command="{Binding OpenPage2Command}" /> </MenuItem> </Menu> <TabControl ItemsSource="{Binding Tabs}" SelectedItem="{Binding SelectedTab}" BorderThickness="0" Background="Transparent"> <TabControl.ItemTemplate> <DataTemplate> <DockPanel> <TextBlock Text="{Binding Header}" Margin="0,0,5,0"/> <Button Content="×" Command="{Binding CloseCommand}" DockPanel.Dock="Right" Background="Transparent" BorderThickness="0"/> </DockPanel> </DataTemplate> </TabControl.ItemTemplate> <TabControl.ContentTemplate> <DataTemplate DataType="domain:TabItemViewModel"> <ContentPresenter Content="{Binding Content, Mode=TwoWay}" /> </DataTemplate> </TabControl.ContentTemplate> </TabControl> </DockPanel>
需要在MainWindow.cs赋值DataContext,需要把ViewModel注册为单例
public MainWindow() { InitializeComponent(); this.DataContext= App.Current.Services.GetService<MainViewModel>(); }
ViewModel,Page1、Page2为需要展示的Page页面
[ObservableProperty] ObservableCollection<TabItemViewModel> _tabs = []; [ObservableProperty] private TabItemViewModel? _selectedTab=new(); private readonly Dictionary<string, Page> _pageCache = new(); [RelayCommand] void OpenPage1() => NewTab("Page1", new Page1()); [RelayCommand] void OpenPage2() => NewTab("Page2", new Page2()); private void NewTab(string header, Page page) { var existing = Tabs.FirstOrDefault(t => t.Header == header); if (existing != null) { SelectedTab = existing; return; } Page loadedPage; if (_pageCache.ContainsKey(header)) { loadedPage = _pageCache[header]; } else { loadedPage = page; _pageCache[header] = loadedPage; } var newTab = new TabItemViewModel ( header,new Frame() {Content=loadedPage }); Tabs.Add(newTab); SelectedTab = newTab; }
TabItemViewModel.cs,获取的parentViewModel 需要是单例,确保移除的是当前窗口的标签
public partial class TabItemViewModel : ObservableObject { [ObservableProperty] private string _Header = "New Tab"; [ObservableProperty] private object _Content = new object(); public TabItemViewModel(string header,Frame frame ) { Header = header; Content = frame; } public TabItemViewModel() { } [RelayCommand] private void Close() { var parentViewModel = App.Current.Services.GetService<MainViewModel>(); if (parentViewModel != null) { parentViewModel.Tabs.Remove(this); } } }
App.xaml.cs 依赖注入,注册单例
/// <summary> /// Ioc服务 /// </summary> public IServiceProvider Services { get; } public new static App Current => (App)Application.Current; public App() { Services = ConfigureServices(); } private static IServiceProvider ConfigureServices() { var services = new ServiceCollection(); services.AddSingleton<MainViewModel>(); services.AddSingleton(sp => new MainWindow { DataContext = sp.GetService<MainViewModel>() }); return services.BuildServiceProvider(); }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/14 16:19:51

从零搭建个人独立博客:Hexo + GitHub Pages 极速建站与踩坑实录

引言作为一名爱折腾的开发者&#xff0c;刚解决完一个极其棘手的 WebGL 3D 网页滚动陷阱 Bug&#xff0c;最爽的事情莫过于把这份血汗经验写成文章分享出来&#xff01;这篇文章将为你带来一份实战教程&#xff0c;完整记录我是如何使用 Hexo 配合 GitHub Pages 建站&#xff0…

作者头像 李华
网站建设 2026/7/14 16:20:07

平行链协议深度拆解 | 一个区块如何穿越六道关卡获得最终确认

原文作者&#xff1a;PaperMoon 团队一个平行链区块要想获得 Polkadot 网络的最终安全背书&#xff0c;需要经历候选、附议、可背书、已背书、待可用、已包含六个状态——任何一步失败都会被丢弃。这套机制的名字听起来很学术&#xff0c;但它解决的问题极其现实&#xff1a;几…

作者头像 李华
网站建设 2026/7/14 16:20:05

什么是管理

什么是管理1.管理是“管事”而不是“管人”&#xff0c;也就是说我们要清晰地界定必须要做的事情&#xff0c;以及做事的标准。虽然管理行为是依据人来判断的&#xff0c;但不能只关心人的态度和表现。 2.就是要让下属明白自己的工作职责&#xff0c;帮助他明确和分析自己要做的…

作者头像 李华
网站建设 2026/7/14 16:20:06

2026论文降重盘点:AIGC严查下谁能活?

摘要/前言&#xff1a; 2026年&#xff0c;还在用老一套的AI方法降重&#xff1f;醒醒&#xff01;高校的检测系统早已迭代&#xff0c;现在是“重复率”“AIGC成分”双重核查。你以为的“降重”&#xff0c;在系统后台可能已标记为“学术不端高危行为”。本文将进行一次硬核盘…

作者头像 李华
网站建设 2026/7/14 16:19:51

如何通过一张照片辨别拍照位置

1如何通过这张照片分辨出是哪个电信公司2将图片保存到桌面&#xff0c;右键找到属性并打开 。点击详细信息3找到该照片的元信息拍摄地点拍摄设备分辨率等信息4接下来我们通过图中的gps获取定位打开谷歌地图在左边搜索输入gps获取的经纬度就可以找到图片拍摄的大概位置再通过大概…

作者头像 李华
网站建设 2026/7/14 16:20:04

景区复购率低迷?全流程服务盘活留量|巨有科技

文旅行业复苏后&#xff0c;绝大多数景区都陷入了同一个运营怪圈&#xff1a;砸重金做营销、拓渠道抢新客&#xff0c;节假日客流爆满看似热闹&#xff0c;可游客离园之后&#xff0c;就彻底和景区断了联系&#xff0c;二次到访、多次复购的游客少之又少&#xff0c;老客留存率…

作者头像 李华