基于HandyControl实现侧边菜单动态加载TabItem的功能

主要功能是点击左侧的 `SideMenu` 项目,然后在右侧的 `TabControl` 中创建一个新的 `TabItem`。这个 `TabItem` 的内容是一个 `TextBlock`,显示的是所点击的 `SideMenuItem` 的 `Header` 文本。代码还包括了关闭 `TabItem` 的功能。

以下是具体实现思路:

1. **创建主窗口**:在 `MainWindow.xaml` 文件中,创建了一个包含 `SideMenu` 和 `TabControl` 的主窗口。`SideMenu` 和 `TabControl` 是分别放在 `Grid` 的两个列中的。

2. **定义数据模型**:在 `MainViewModel` 类中,定义了数据模型。这个数据模型包括一个 `ObservableCollection`,用于存储 `TabItem` 对象,以及两个命令,用于处理用户的操作。

3. **处理用户的点击操作**:在 `MainWindow.xaml.cs` 文件的 `MainWindow` 类中定义了 `MenuButton_Click` 方法,用于处理用户点击 `SideMenuItem` 的操作。在这个方法中,创建了一个新的 `TabItem`,并把它添加到 `TabControl` 中。

4. **关闭 `TabItem`**:在 `MainViewModel` 类中定义了 `RemoveTabCommand` 命令,用于关闭 `TabItem`。在 `MainWindow.xaml` 文件中,为每个 `TabItem` 添加了一个关闭按钮,并绑定了这个命令。

5. **显示 `TabItem` 的内容**:在 `MainWindow.xaml` 文件中为 `TabControl` 定义了 `ContentTemplate`,用于显示 `TabItem` 的内容。

6. **数据绑定**:在 `MainWindow.xaml.cs` 文件的 `MainWindow` 类的构造函数中,把 `MainViewModel` 对象设置为主窗口的 `DataContext`,以便在 XAML 中进行数据绑定。

7. **动态创建 `TabItem` 的内容**:在 `SelectCmd` 命令的实现中,根据 `SideMenuItem` 的 `Name` 动态创建了 `TabItem` 的内容。

这是主要实现思路。代码结构清晰,逻辑明确。可以在这个基础上添加更多的功能,比如支持拖拽排序 `TabItem`,或者在 `TabControl` 中显示更复杂的内容。

XAML代码:

<Window x:Class="WpfApp1.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:WpfApp1"xmlns:hc="https://handyorg.github.io/handycontrol"mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"><Window.Resources><local:MultiValueConverter x:Key="MultiValueConverter"/></Window.Resources><Grid><Grid><Grid.ColumnDefinitions><ColumnDefinition Width="Auto"/><ColumnDefinition/></Grid.ColumnDefinitions><hc:SideMenu Grid.Column="0" Width="200" x:Name="sideMenu"  ExpandMode="ShowOne"><hc:SideMenuItem Header="大屏展示"><hc:SideMenuItem.Icon><Image Source="../Images/DevOps-Overview.png" Width="24" Height="24"/></hc:SideMenuItem.Icon><hc:SideMenuItem Header="(正式)视觉大屏"  x:Name="VisualLargeScreen" Command="{Binding SelectCmd}"><hc:SideMenuItem.Icon><Image Source="../Images/DevOps-Pipelines.png" Width="12" Height="12"/></hc:SideMenuItem.Icon><hc:SideMenuItem.CommandParameter><MultiBinding Converter="{StaticResource MultiValueConverter}"><Binding Path="Header" RelativeSource="{RelativeSource Self}"/><Binding Path="Name" RelativeSource="{RelativeSource Self}"/></MultiBinding></hc:SideMenuItem.CommandParameter></hc:SideMenuItem><hc:SideMenuItem Header="(正式)打磨大屏"  x:Name="PolishinLargeScreen" Command="{Binding SelectCmd}"><hc:SideMenuItem.Icon><Image Source="../Images/DevOps-Repos.png" Width="12" Height="12"/></hc:SideMenuItem.Icon><hc:SideMenuItem.CommandParameter><MultiBinding Converter="{StaticResource MultiValueConverter}"><Binding Path="Header" RelativeSource="{RelativeSource Self}"/><Binding Path="Name" RelativeSource="{RelativeSource Self}"/></MultiBinding></hc:SideMenuItem.CommandParameter></hc:SideMenuItem></hc:SideMenuItem><hc:SideMenuItem Header="基础信息查询"><hc:SideMenuItem.Icon><Image Source="../Images/DevOps-TestPlans.png" Width="24" Height="24"/></hc:SideMenuItem.Icon></hc:SideMenuItem><!-- Add more menu buttons here --></hc:SideMenu><hc:TabControl Grid.Column="1" x:Name="tabControl" ItemsSource="{Binding TabItems}" ShowCloseButton="True"><hc:TabControl.ItemTemplate><!-- This is the header template--><DataTemplate><DockPanel Width="120"><Button Command="{Binding DataContext.RemoveTabCommand, RelativeSource={RelativeSource AncestorType={x:Type hc:TabControl}}}" CommandParameter="{Binding}" Content="X" DockPanel.Dock="Right" /><ContentPresenter Content="{Binding Header}" /></DockPanel></DataTemplate></hc:TabControl.ItemTemplate><hc:TabControl.ContentTemplate><DataTemplate><Grid   HorizontalAlignment="Stretch"  VerticalAlignment="Stretch" ><ContentPresenter Content="{Binding Content}"></ContentPresenter></Grid></DataTemplate></hc:TabControl.ContentTemplate></hc:TabControl></Grid></Grid>
</Window>

后端代码:

using HandyControl.Controls;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;namespace WpfApp1
{/// <summary>/// Interaction logic for MainWindow.xaml/// </summary>public partial class MainWindow : System.Windows.Window{MainViewModel viewModel;public MainWindow(){InitializeComponent();viewModel=new MainViewModel();this.DataContext = viewModel;viewModel.TabItems = new ObservableCollection<HandyControl.Controls.TabItem>();viewModel.RemoveTabCommand = new RelayCommand(param =>{HandyControl.Controls.TabItem tabItem = param as HandyControl.Controls.TabItem;viewModel.TabItems.Remove(tabItem);});viewModel.SelectCmd = new RelayCommand(param =>{var str = param as Tuple<string, string>;if (str != null){Type type = Type.GetType("WpfApp1." + str.Item2);object instance = Activator.CreateInstance(type);HandyControl.Controls.TabItem SelectedtabItem = viewModel.TabItems.FirstOrDefault(p => p.Header == str.Item1);if (SelectedtabItem != null){SelectedtabItem.IsSelected = true;return;}viewModel.TabItems.Add(new HandyControl.Controls.TabItem() { IsSelected = true, Header = str.Item1, Content = instance });}});}private void MenuButton_Click(object sender, RoutedEventArgs e){var menuItem = (SideMenuItem)sender;var tabItem = new HandyControl.Controls.TabItem{Header = menuItem.Header,Content = new TextBlock { Text = $"Content for {menuItem.Header}" }};var closeButton = new Button{Content = "Close",Width = 75,Height = 25};closeButton.Click += (s, e) => { tabControl.Items.Remove(tabItem); };var stackPanel = new StackPanel();stackPanel.Children.Add(closeButton);stackPanel.Children.Add(tabItem);tabControl.Items.Add(stackPanel);}}
}

数据模型代码:

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;namespace WpfApp1
{public class MainViewModel : INotifyPropertyChanged{private ObservableCollection<HandyControl.Controls.TabItem> _tabItems;public ObservableCollection<HandyControl.Controls.TabItem> TabItems{get { return _tabItems; }set{_tabItems = value;OnPropertyChanged();}}/// <summary>/// 关闭tabitem显示的页面/// </summary>public ICommand RemoveTabCommand { get; set; }public ICommand SelectCmd { get; set; }public event PropertyChangedEventHandler? PropertyChanged;protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null){PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/35171.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

代码随想录算法训练营第四十一天|01背包问题 二维 01背包问题 一维 416. 分割等和子集

卡码网 01背包问题 二维 题目链接&#xff1a;01背包问题 二维 踩坑&#xff1a;在考虑当前物品时&#xff0c;应先考虑当前的背包能不能放得下当前物品 思路&#xff1a; 动态数组的含义&#xff1a;dp[i][j]&#xff1a;物品[0, i]在容量为 j 的背包中的最大价值递推公式…

【PyTorch函数解析】einsum的用法示例

一、前言 einsum 是一个非常强大的函数&#xff0c;用于执行张量&#xff08;Tensor&#xff09;运算。它的名称来源于爱因斯坦求和约定&#xff08;Einstein summation convention&#xff09;&#xff0c;在PyTorch中&#xff0c;einsum 可以方便地进行多维数组的操作和计算…

MySQL中服务器状态变量全解(一)

MySQL 服务器维护了许多状态变量&#xff0c;这些变量提供了关于其操作的信息。您可以使用 SHOW [GLOBAL | SESSION] STATUS 语句来查看这些变量及其值。 GLOBAL 关键字&#xff08;可选&#xff09;用于显示所有连接的聚合值。这些值通常表示自MySQL服务器启动以来的累计统计…

DWC USB2.0协议学习1--产品概述

本章开始学习记录DWC_otg控制器&#xff08;新思USB2.0&#xff09;的特点、功能和应用。 新思USB 2.0 IP主要有两个文档需要参考&#xff1a; 《DesignWare Cores USB 2.0 Hi-Speed On-TheGo (OTG) Data book》 《DesignWare Cores USB 2.0 Hi-Speed On-TheGo (OTG) Progra…

Leetcode85 01矩阵中的最大矩形

题目描述 给定一个仅包含 0 和 1 、大小为 rows x cols 的二维二进制矩阵&#xff0c;找出只包含 1 的最大矩形&#xff0c;并返回其面积。 解题思路 动态规划的思想&#xff0c;记录每一个位置向上能到达的最大高度&#xff0c;和向左能到达的最大宽度。 在一个点进行遍历时…

解决IMX6ULL GPIO扩展板PWM7/8中的pwm0/period后卡死问题

前言 本篇文章主要是记录解决百问网论坛上面设置 IMX6ULL GPIO扩展板PWM7/8中的pwm0/period后卡死问题&#xff0c;如下图&#xff1a; 一、查看原理图&#xff0c;找出对应引脚 在这里我们如何确定哪个扩展口中的引脚输出PWM波呢&#xff1f;我们可以通过查看原理图。 查看…

作业6.20

1.已知网址www.hqyj.com截取出网址的每一个部分(要求&#xff0c;该网址不能存入文件中) 2.将配置桥接网络的过程整理成文档&#xff0c;发csdn 步骤i&#xff1a;在虚拟机设置中启用桥接模式 1. 打开VMware虚拟机软件。 2. 选择您想要配置的虚拟机&#xff0c;点击菜单栏中的“…

C++ 基础:指针和引用浅谈

指针 基本概念 在C中&#xff0c;指针是存储其他变量的内存地址的变量。 我们在程序中声明的每个变量在内存中都有一个关联的位置&#xff0c;我们称之为变量的内存地址。 如果我们的程序中有一个变量 var&#xff0c;那么&var 返回它的内存地址。 int main() {int var…

北大医院副院长李建平:用AI解决临床心肌缺血预测的难点、卡点和痛点

2024年6月14日&#xff0c;第六届北京智源大会在中关村展示中心开幕&#xff0c;海内外的专家学者围绕人工智能关键技术路径和应用场景&#xff0c;展开了精彩演讲与尖峰对话。在「智慧医疗和生物系统&#xff1a;影像、功能与仿真」论坛上&#xff0c;北京大学第一医院副院长、…

孩子不想上学,父母应如何教育?“强迫教育”会激起孩子反抗心理

上周末朋友聚会&#xff0c;都是家有上学娃的年纪&#xff0c;闲聊中&#xff0c;话题自然少不了孩子的上学问题。其中&#xff0c;不少朋友都有抱怨过同一个问题&#xff1a;孩子不想上学&#xff0c;即使人到了学校&#xff0c;心也不在学校。   事实上&#xff0c;孩子出现…

java复习宝典,jdbc与mysql数据库

一.java 1.面向对象知识 (1)类和对象 类&#xff1a;若干具有相同属性和行为的对象的群体或者抽象&#xff0c;类是创建对象的模板&#xff0c;由属性和行为两部分组成。 类是对象的概括或者抽象&#xff0c;对象是类的实例化。 举例&#xff1a;例如车有很多类型&#xf…

安卓ROM修改默认开启adb调试

要在安卓ROM中修改默认开启ADB调试&#xff0c;你可以遵循以下步骤。请注意&#xff0c;这些步骤可能因设备型号、ROM版本和具体定制方式而有所不同&#xff0c;但基本流程是相似的&#xff1a; 准备工作&#xff1a; 确保你有一台可root的安卓手机&#xff0c;并且已经解锁了…

计算机系统基础知识(下)

嵌入式系统以及软件 嵌入式系统是为了特定应用而专门构建且将信息处理过程和物理过程紧密结合为一体的专用计算机系统&#xff0c;这个系统目前以涵盖军事&#xff0c;自动化&#xff0c;医疗&#xff0c;通信&#xff0c;工业控制&#xff0c;交通运输等各个应用领域&#xff…

鸿蒙开发Ability Kit(程序框架服务):【Stage模型绑定FA模型ServiceAbility】

Stage模型绑定FA模型ServiceAbility 本小节介绍Stage模型的两种应用组件如何绑定FA模型ServiceAbility组件。 UIAbility关联访问ServiceAbility UIAbility关联访问ServiceAbility和UIAbility关联访问ServiceExtensionAbility的方式完全相同。 import { common, Want } from…

【Matlab 六自由度机器人】机器人动力学之推导拉格朗日方程(附MATLAB机器人动力学拉格朗日方程推导代码)

【Matlab 六自由度机器人】机器人动力学概述 近期更新前言正文一、拉格朗日方程的推导1. 单自由度系统2. 单连杆机械臂系统3. 双连杆机械臂系统 二、MATLAB实例推导1. 机器人模型的建立2. 动力学代码 总结参考文献 近期更新 【汇总】 【Matlab 六自由度机器人】系列文章汇总 …

Linux——31个普通信号

每种信号的含义 在Linux操作系统中&#xff0c;信号是一种进程间通信的方式&#xff0c;用于通知进程发生了某种事件。Linux中的普通信号&#xff08;standard signals&#xff09;有31个&#xff0c;每个信号都有特定的用途。以下是这31个普通信号的列表及其描述&#xff1a;…

为什么序列化???

跨进程调用&#xff0c;进行数据传输时&#xff0c;无法直接传递对象&#xff0c;需要将对象通过序列化的方式转为字节流或字符流&#xff08;json&#xff09;&#xff0c;所以需要进行序列化。 需要共享数据时&#xff0c;直接传递对象通常是不可行的&#xff0c;因为对象的…

C# UDP网络通信

TCP和UDP基本概念 TCP:(Transmission Control Protocol)是一种面向连接、可靠的、基于字节流的传输层通信协议。并且提供了全双工通信&#xff0c;允许俩个应用直接建立一个可靠的连接 以进行数据交换 /UDP:(User Datagram Protocol):是一种无连接、不可靠、基于数据报文传输层…

每日复盘-20240625

今日关注: 20240625 六日涨幅最大: ------1--------300930--------- 屹通新材 五日涨幅最大: ------1--------300930--------- 屹通新材 四日涨幅最大: ------1--------300386--------- 飞天诚信 三日涨幅最大: ------1--------300386--------- 飞天诚信 二日涨幅最大: ------…

JVM专题十:JVM中的垃圾回收机制

在JVM专题九&#xff1a;JVM分代知识点梳理中&#xff0c;我们主要介绍了JVM为什么采用分代算法&#xff0c;以及相关的概念&#xff0c;本篇我们将详细拆分各个算法。 垃圾回收的概念 垃圾回收&#xff08;Garbage Collection&#xff0c;GC&#xff09;确实是计算机编程中的…