<!-- 2025年4月4日 00:15 代码注释(乙巳蛇年三月初七 星期五) -->
<StackPanel Margin="15">
<!-- 〖课程大纲导航系统〗 -->
<TextBlock Text="控件课程" FontWeight="Bold" FontSize="16"/> <!-- 建议添加课程标识图标 -->
<!-- 〖交互式教学模块 - Button控件〗 -->
<Expander Header="Button控件"
ExpandDirection="Down"
Expanded="Expander_Expanded" <!-- 需在后端实现展开动画逻辑 -->
Collapsed="Expander_Collapsed" <!-- 建议添加折叠过渡效果 -->
Style="{StaticResource ModernExpanderStyle}"> <!-- 推荐样式标准化 -->
<Grid Background="#FFE5E5E5"> <!-- 硬编码颜色值建议改用DynamicResource -->
<TextBlock Padding="10" TextWrapping="Wrap"
Typography.Capitals="SmallCaps"> <!-- 增强排版美观性 -->
[!] 技术要点:
1. 事件响应机制:Click事件继承自ButtonBase
2. 内容模型特性:支持任意类型Content(文本/图像/自定义控件)
3. 命令绑定扩展:建议集成ICommand实现MVVM模式
</TextBlock>
</Grid>
</Expander>
<!-- 〖数据输入教学模块 - TextBox控件〗 -->
<Expander Header="TextBox控件"
ExpandDirection="Left" <!-- 横向展开需注意布局兼容性 -->
ToolTip="文本输入核心组件">
<Grid Background="#FFE5E5E5">
<TextBlock Padding="10" TextWrapping="Wrap">
[!] 进阶知识:
• 输入验证:可集成IDataErrorInfo实现实时校验
• 多行模式:需显式设置AcceptsReturn="True"
• 文本格式化:通过StringFormat绑定实现数据转换
• 性能隐患:大数据量输入需考虑延迟加载
</TextBlock>
</Grid>
</Expander>
<!-- 〖集合展示教学模块 - ListBox控件〗 -->
<Expander Header="ListBox控件"
ExpandDirection="Right" <!-- 建议统一展开方向 -->
IsTabStop="True"> <!-- 增强键盘导航功能 -->
<Grid Background="#FFE5E5E5">
<TextBlock Padding="10" TextWrapping="Wrap">
[!] 工程实践:
1. 数据绑定:优先使用ItemsSource而非手动添加Item
2. 虚拟化技术:启用VirtualizingStackPanel提升性能
3. 模板定制:通过ItemTemplate实现个性化展示
4. 选择模式:支持Single/Extended/Multiple等模式
</TextBlock>
</Grid>
</Expander>
</StackPanel>
/*
█████████████████████████████████████████████████████████████████
【系统架构优化方案】
█████████████████████████████████████████████████████████████████
一、组件化改造
1. 创建可复用教学模块模板
```xml
<ControlTemplate x:Key="CourseExpanderTemplate" TargetType="Expander">
<Border Background="{TemplateBinding Background}" CornerRadius="5">
<ContentPresenter RecognizesAccessKey="True"/>
</Border>
</ControlTemplate>
<!-- 主容器:使用Grid布局分为3行 -->
<Grid>
<!-- 行定义:首行自适应,第二、三行根据内容自动调整高度 -->
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<!-- 媒体显示区域:嵌套Grid实现媒体层与文字层的叠加 -->
<Grid>
<!-- 媒体播放器组件,初始加载模式为手动控制 -->
<MediaElement x:Name="_Media" LoadedBehavior="Manual"/>
<!-- 半透明遮罩层,用于显示媒体状态文字 -->
<Border x:Name="_Border" Background="Black">
<TextBlock x:Name="_txtBlock"
Text="MediaElement | 媒体播放器"
Foreground="LightCoral"
FontSize="20"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
</Grid>
<!-- 控制面板:水平排列的按钮组和音量控制 -->
<StackPanel Orientation="Horizontal" Grid.Row="1">
<!-- 媒体控制按钮组 -->
<Button Content="打开" Click="OpenMedia" .../>
<Button Content="播放" Click="PlayMedia" .../>
<Button Content="停止" Click="StopMedia" .../>
<Button Content="后退" Click ="BackMedia" .../>
<Button Content="前进" Click="ForwardMedia" .../>
<!-- 音量控制组件 -->
<TextBlock Text="音量" .../>
<Slider x:Name="_Slider"
Maximum="100"
Value="50" <!-- 默认音量50% -->
ValueChanged="_Slider_ValueChanged"/>
</StackPanel>
<!-- 进度条显示区域 -->
<Grid Grid.Row="2">
<ProgressBar x:Name="_ProgressBar"
Height="10"
Margin="5"
<!-- 建议添加与媒体播放进度的绑定 -->
/>
</Grid>
</Grid>
// 创建调度定时器实例(基于UI线程的计时器,适合更新界面元素)
DispatcherTimer timer = new DispatcherTimer();
// 设置定时器触发间隔为1秒(注意:此处参数应为TimeSpan.FromSeconds(1)更规范)
timer.Interval = TimeSpan.FromMilliseconds(1000);
// 绑定定时器触发事件
timer.Tick += (s, e) =>
{
// 获取媒体元素的当前播放位置
var ts = _Media.Position;
// 更新进度条数值(需配合设置进度条最大值)❗
// 当前实现问题:未关联媒体总时长,建议添加:
// _ProgressBar.Maximum = _Media.NaturalDuration.TimeSpan.TotalMilliseconds;
_ProgressBar.Value = ts.TotalMilliseconds;
};
// 启动定时器(注意需在媒体加载后启动)⏯️
timer.Start();
/* 优化建议:
1. 定时器精度:将Interval改为250ms提升进度条流畅度(如TimeSpan.FromMilliseconds(250))
2. 异常处理:添加try-catch块防止媒体未加载时访问Position属性报错
3. 暂停机制:媒体停止时执行timer.Stop()节省资源
4. 双向绑定:可添加进度条拖动事件反向设置_Position实现进度拖拽
5. 时间显示:扩展显示当前时间/总时长文本(如"02:30 / 05:00")
*/
// 全局变量声明
private string file = string.Empty; // 存储当前媒体文件路径(建议改为属性封装)
/// <summary>
/// 打开媒体文件事件处理
/// </summary>
private void OpenMedia(object sender, RoutedEventArgs e)
{
// 创建文件对话框(注意拼写应为openFileDialog)
var opneFileDialog = new Microsoft.Win32.OpenFileDialog()
{
Filter = "视频文件(.mp4)|*.mp4", // 文件过滤格式(可扩展为多格式支持)
Multiselect = true, // 支持多选但未实现多文件处理
};
// 显示对话框并处理结果
var result = opneFileDialog.ShowDialog();
if (result == true)
{
file = opneFileDialog.FileName;
_Media.MediaOpened += _Media_MediaOpened; // 可能多次订阅导致内存泄漏(建议先取消订阅)
_Media.Source = new System.Uri(file); // 设置媒体源(需添加URI验证)
this.Title = file; // 更新窗口标题
_txtBlock.Text = file; // 更新状态文字(建议路径截断显示)
}
// 缺失:else分支处理取消操作
}
/// <summary>
/// 媒体加载完成事件处理
/// </summary>
private void _Media_MediaOpened(object sender, RoutedEventArgs e)
{
if(_Media.NaturalDuration.HasTimeSpan) // 验证是否包含时间跨度
{
var ts = _Media.NaturalDuration.TimeSpan;
_ProgressBar.Maximum = ts.TotalMilliseconds; // 设置进度条最大值(需绑定前端显示)
// 缺失:初始化进度条当前值
}
}
/// <summary>
/// 播放控制逻辑
/// </summary>
private void PlayMedia(object sender, RoutedEventArgs e)
{
_Media.Play(); // 开始播放
_Border.Visibility = Visibility.Collapsed; // 隐藏状态遮罩(可改为渐变动画)
}
private void StopMedia(object sender, RoutedEventArgs e)
{
_Media.Pause(); // 实际是暂停而非停止(建议区分Pause/Stop)
// 缺失:恢复播放按钮状态
}
/// <summary>
/// 媒体定位控制
/// </summary>
private void BackMedia(object sender, RoutedEventArgs e)
{
var newPos = _Media.Position - TimeSpan.FromSeconds(10);
_Media.Position = newPos > TimeSpan.Zero ? newPos : TimeSpan.Zero; // 添加边界检查
}
private void ForwardMedia(object sender, RoutedEventArgs e)
{
var newPos = _Media.Position + TimeSpan.FromSeconds(10);
if (newPos < _Media.NaturalDuration.TimeSpan) // 防止越界
{
_Media.Position = newPos;
}
}
/// <summary>
/// 音量控制事件处理
/// </summary>
private void _Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
_Media.Volume = _Slider.Value / 100; // 修正音量计算(MediaElement.Volume范围0-1)
// 缺失:显示当前音量百分比
}

<Window x:Class="HelloWorld.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:HelloWorld"
mc:Ignorable="d"
Title="HelloWorld" Height="350" Width="500">
<Grid>
<TextBlock Text="Hello,World!" FontSize="48"/>
</Grid>
</Window>
关键字/属性 | 所在位置 | 作用说明 | 代码示例 |
---|
Window | 根元素 | 定义WPF应用程序的主窗口容器 | <Window ...>...</Window> |
x:Class | Window元素属性 | 指定窗口关联的后台C#类(命名空间+类名) | x:Class="HelloWorld.MainWindow" |
xmlns | Window元素属性 | XML命名空间声明,用于引用WPF核心库 | xmlns="http://...xaml/presentation" |
xmlns:x | Window元素属性 | 定义XAML语言特性的专用命名空间 | xmlns:x="http://...xaml" |
xmlns:d | Window元素属性 | 设计器命名空间(d:DesignHeight等设计时属性) | xmlns:d="http://...blend/2008" |
xmlns:mc | Window元素属性 | 标记兼容性声明,用于XAML解析器的忽略处理 | xmlns:mc="http://...compatibility/2006" |
mc:Ignorable | Window元素属性 | 指定可被设计器忽略的命名空间(此处忽略d命名空间) | mc:Ignorable="d" |
Title | Window元素属性 | 设置窗口标题栏显示文本 | Title="HelloWorld" |
Height/Width | Window元素属性 | 定义窗口初始高度和宽度(单位:设备无关像素) | Height="350" Width="500" |
Grid | 布局元素 | 创建网格布局容器,默认单行单列 | <Grid>...</Grid> |
TextBlock | 内容控件 | 显示静态文本的轻量级控件 | <TextBlock Text="Hello,World!"/> |
FontSize | TextBlock属性 | 设置文本字号(单位:设备无关像素) | FontSize="48" |