当前位置: 首页 > news >正文

WPF 重写Expander

效果图
image

<UserControl x:Class="BlackBoard.UserControls.ColorExpander"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:BlackBoard.UserControls"mc:Ignorable="d"              x:Name="rootControl"xmlns:usercontrols="clr-namespace:BlackBoard.UserControls"d:DesignHeight="450" d:DesignWidth="800"><UserControl.Resources><!-- 定义统一的背景色变量 --><SolidColorBrush x:Key="HeaderBackgroundBrush" Color="#D4F7EA"/><Style x:Key="ExpanderStyle" TargetType="{x:Type Expander}"><Setter Property="IsExpanded" Value="False"></Setter><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type Expander}"><Grid><Grid.RowDefinitions><RowDefinition Height="auto"></RowDefinition><RowDefinition Height="auto"></RowDefinition></Grid.RowDefinitions><Border BorderThickness="0" Background="{DynamicResource HeaderBackgroundBrush}" ><Grid><Grid.ColumnDefinitions><ColumnDefinition Width="auto"/><ColumnDefinition/></Grid.ColumnDefinitions><!-- 将ToggleButton放在第一行,覆盖整个Header区域 --><ToggleButton x:Name="HeaderSite" Grid.ColumnSpan="2" Background="Transparent" Margin="0" Padding="0"IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"                                  Style="{DynamicResource ExpanderToggleButtonStyle}" ><ToggleButton.Content><!-- 在ToggleButton内部放置Header内容 --><DockPanel HorizontalAlignment="Stretch" Background="{DynamicResource HeaderBackgroundBrush}"><!-- 小三角图标容器,设置与Header相同的背景色 --><Border Width="20" Background="{DynamicResource HeaderBackgroundBrush}" DockPanel.Dock="Left"><Canvas Width="12" Height="12" VerticalAlignment="Center" HorizontalAlignment="Center"><!-- 使用RenderTransform实现旋转效果 --><Path x:Name="expanderArrow"Data="M0,0 L8,4 L0,8 Z" Stroke="Black" StrokeThickness="2"Fill="Black"Canvas.Left="2"Canvas.Top="2"RenderTransformOrigin="0.5,0.5"><Path.RenderTransform><RotateTransform Angle="0"/></Path.RenderTransform></Path></Canvas></Border><!-- 实际Header内容 --><ContentPresenter ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" VerticalAlignment="Center"Margin="0,0,0,0"/></DockPanel></ToggleButton.Content></ToggleButton></Grid></Border><ContentPresenter x:Name="ExpandSite" Grid.Row="1" Margin="0"ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Visibility="Collapsed" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/></Grid><ControlTemplate.Triggers><Trigger Property="IsExpanded" Value="True"><Setter Property="Visibility" TargetName="ExpandSite" Value="Visible"/><!-- 当展开时,旋转小三角90度 --><Setter TargetName="expanderArrow" Property="RenderTransform"><Setter.Value><RotateTransform Angle="90"/></Setter.Value></Setter></Trigger><Trigger Property="IsExpanded" Value="False"><!-- 当收起时,恢复原始角度 --><Setter TargetName="expanderArrow" Property="RenderTransform"><Setter.Value><RotateTransform Angle="0"/></Setter.Value></Setter></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style><Style x:Key="ExpanderToggleButtonStyle" TargetType="{x:Type ToggleButton}"><Setter Property="FocusVisualStyle" Value="{x:Null}"/><Setter Property="Background" Value="Transparent" /><Setter Property="Foreground" Value="Gainsboro"/><Setter Property="FontSize" Value="15" /><Setter Property="FontFamily" Value="宋体" /><Setter Property="FontWeight" Value="Bold" /><Setter Property="BorderThickness" Value="0"/><Setter Property="HorizontalContentAlignment" Value="Stretch"/><Setter Property="VerticalContentAlignment" Value="Center"/><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type ToggleButton}"><Grid Background="Transparent"><ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True"                       SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/></Grid><ControlTemplate.Triggers><Trigger Property="IsPressed" Value="true"><!-- 鼠标按下时,可以添加轻微的透明度变化来表示交互 --><Setter Property="Opacity" Value="0.9"/></Trigger><Trigger Property="IsChecked" Value="true"><!-- 这里通过动画或样式更改来显示展开状态 --></Trigger><Trigger Property="IsEnabled" Value="false"><Setter Property="Foreground" Value="Gray"/></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style></UserControl.Resources><Grid><Expander HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" Padding="0" Margin="0" Style="{StaticResource ExpanderStyle}"><Expander.Header><DockPanel HorizontalAlignment="Stretch" Background="{DynamicResource HeaderBackgroundBrush}" Margin="0" Height="30" ><StackPanel Orientation="Horizontal" DockPanel.Dock="Left" HorizontalAlignment="Stretch" VerticalAlignment="Center"><TextBlock Name="lblTitle" Text="" Margin="5,0" FontSize="12" FontWeight="Bold"/></StackPanel></DockPanel></Expander.Header><ContentPresenter Name="content"/></Expander></Grid>
</UserControl>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;namespace BlackBoard.UserControls
{/// <summary>/// ColorExpander.xaml 的交互逻辑/// </summary>public partial class ColorExpander : UserControl{public string Title{get { return (string)GetValue(TitleProperty); }set { SetValue(TitleProperty, value); }}// Using a DependencyProperty as the backing store for Title.  This enables animation, styling, binding, etc...public static readonly DependencyProperty TitleProperty =DependencyProperty.Register(nameof(Title), typeof(string), typeof(ColorExpander), new PropertyMetadata(string.Empty, OnTitleChange));private static void OnTitleChange(DependencyObject d, DependencyPropertyChangedEventArgs e){var control = (ColorExpander)d;if (e.NewValue is string value){control.Dispatcher.Invoke(() =>{control.lblTitle.Text = value;});}}public string BGColor{get { return (string)GetValue(ColorProperty); }set { SetValue(ColorProperty, value); }}// Using a DependencyProperty as the backing store for Color.  This enables animation, styling, binding, etc...public static readonly DependencyProperty ColorProperty =DependencyProperty.Register(nameof(BGColor), typeof(string), typeof(ColorExpander), new PropertyMetadata(string.Empty, OnColorChange));private static void OnColorChange(DependencyObject d, DependencyPropertyChangedEventArgs e){var control = (ColorExpander)d;if (e.NewValue is string value){control.Dispatcher.Invoke(() =>{if (!string.IsNullOrEmpty(value)){// 获取当前的SolidColorBrushvar brush = (SolidColorBrush)control.FindResource("HeaderBackgroundBrush");if (brush != null){brush.Color = (Color)ColorConverter.ConvertFromString(value);}}});}}public object Body{get { return (object)GetValue(BodyProperty); }set { SetValue(BodyProperty, value); }}// Using a DependencyProperty as the backing store for Body.  This enables animation, styling, binding, etc...public static readonly DependencyProperty BodyProperty =DependencyProperty.Register(nameof(Body), typeof(object), typeof(ColorExpander), new PropertyMetadata(null, OnBodyChange));private static void OnBodyChange(DependencyObject d, DependencyPropertyChangedEventArgs e){var control = (ColorExpander)d;if (e.NewValue is object value){control.Dispatcher.Invoke(() =>{control.content.Content = value;});}}public ColorExpander(){InitializeComponent();}}
}

使用

<usercontrols:ColorExpander BGColor="#FF9F3A" Title="A  [ 3人 / 占 12.5% ]"><usercontrols:ColorExpander.Body><ScrollViewer VerticalScrollBarVisibility="Auto" MaxHeight="200"><StackPanel Orientation="Horizontal" Margin="0 10"><Border Background="#F5F5F5" CornerRadius="3" Padding="8" Margin="0,0,8,5"><TextBlock Text="张三张三" Foreground="#333"/></Border><Border Background="#F5F5F5" CornerRadius="3" Padding="8" Margin="0,0,8,5"><TextBlock Text="李四" Foreground="#333"/></Border><Border Background="#F5F5F5" CornerRadius="3" Padding="8" Margin="0,0,8,5"><TextBlock Text="王五" Foreground="#333"/></Border></StackPanel></ScrollViewer></usercontrols:ColorExpander.Body>
</usercontrols:ColorExpander>
http://www.jsqmd.com/news/374695/

相关文章:

  • AI教材生成新方法,低查重效果显著,快速打造专属教材
  • 白菜大模型推理平台(baicai大模型推理平台)——普惠型全栈AI推理服务,赋能企业数字化转型(全新赋能版) - 品牌评测官
  • 深度学习实战(基于pytroch)系列(二十五)深度卷积神经网络(AlexNet) - 指南
  • Java毕设项目推荐-基于springboot与Vue的美食分享平台设计与实现基于springboot的美食分享网站设计与实现【附源码+文档,调试定制服务】
  • RAGFlow 0.24.0 — Memory API、RAG 及 Agent 增强
  • 【毕业设计】基于springboot的美食分享网站设计与实现(源码+文档+远程调试,全bao定制等)
  • 天猫超市卡变现攻略:让闲置卡不再浪费 - 团团收购物卡回收
  • AI写专著必备!专业工具推荐,助力高效产出学术专著
  • 投资人视角:只点一二虾滑自助火锅的效率模型与护城河拆解 - 短商
  • 大量小面值沃尔玛礼品卡回收全攻略 - 京回收小程序
  • 2026卫生高级职称考试哪个题库性价比高?综合实测+高性价比排名推荐 - 医考机构品牌测评专家
  • 一文讲透|专科生专属AI论文平台 —— 千笔AI
  • AI教材生成秘籍:低查重实现,高效完成教材写作任务
  • 外卖员和保安的矛盾分析--ai
  • GraphRAG 里,[Data: Sources (0, 7); Reports (0)] 是结论溯源元数据标记
  • STC89C52单片机出租车计价器设计
  • 天猫超市卡回收实战技巧:简单又高效 - 团团收购物卡回收
  • 万里通积分卡回收攻略:快速搞定流程及省钱技巧! - 团团收购物卡回收
  • 导师又让重写?千笔·降AI率助手 VS WPS AI,本科生专属降AI率工具
  • 低查重AI教材生成秘籍大公开!专业工具助你高效编写优质教材
  • 这次终于选对AI论文软件,千笔AI VS 文途AI,MBA写作更高效!
  • 基于STM32的电池保护板设计
  • 装修公司哪家服务靠谱?2026年北京装修公司推荐与排名,直击售后与交付痛点 - 十大品牌推荐
  • 记住,生产级RAG的核心不在于“大模型选了好”
  • 论文写不动?AI论文平台 千笔ai写作 VS speedai,专为本科生量身打造!
  • 基于单片机的行车记录仪模拟系统设计
  • 沃尔玛礼品卡回收主要流行的三种方式 - 京回收小程序
  • 寒假15
  • 土左供电公司
  • 深入解析:数据仓库基本概念