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

【WPF】WPF 项目实战:用ObservableCollection构建一个可增删、排序的管理界面(含源码)

💡WPF 项目实战:构建一个可增删、排序的光源类型管理界面(含源码)

在实际的图像处理项目中,我们经常需要对“光源类型”进行筛选或管理。今天我们来一步步构建一个实用的 WPF 界面,实现以下功能:

  • ✅ 添加新的光源类型
  • ❌ 删除已有光源类型
  • 🔼🔽 调整光源类型显示顺序
  • 🧠 使用标准的 MVVM 模式 + Prism 命令绑定

🏗️ 第一步:定义模型类

我们为每个光源项定义一个类 LightSourceFilterItem,它包含两个属性:光源名称、是否勾选。

public class LightSourceFilterItem : BindableBase
{public string Name { get; }private bool _isChecked;public bool IsChecked{get => _isChecked;set => SetProperty(ref _isChecked, value);}public LightSourceFilterItem(string name){Name = name;IsChecked = true;}
}

🧠 第二步:ViewModel 实现逻辑

ViewModel 是整个逻辑核心,包括添加、删除、排序命令。

public class LightTypeViewModel : BindableBase
{public ObservableCollection<LightSourceFilterItem> LightSourceItems { get; } = new();private string _newLightSourceName;public string NewLightSourceName{get => _newLightSourceName;set => SetProperty(ref _newLightSourceName, value);}public DelegateCommand AddLightSourceCommand { get; }public DelegateCommand<LightSourceFilterItem> RemoveLightSourceCommand { get; }public DelegateCommand<LightSourceFilterItem> MoveUpCommand { get; }public DelegateCommand<LightSourceFilterItem> MoveDownCommand { get; }public LightTypeViewModel(){AddLightSourceCommand = new DelegateCommand(AddLightSource);RemoveLightSourceCommand = new DelegateCommand<LightSourceFilterItem>(RemoveLightSource);MoveUpCommand = new DelegateCommand<LightSourceFilterItem>(MoveUp);MoveDownCommand = new DelegateCommand<LightSourceFilterItem>(MoveDown);}private void AddLightSource(){if (string.IsNullOrWhiteSpace(NewLightSourceName)) return;if (LightSourceItems.Any(x => x.Name == NewLightSourceName)) return;LightSourceItems.Add(new LightSourceFilterItem(NewLightSourceName));NewLightSourceName = string.Empty;}private void RemoveLightSource(LightSourceFilterItem item){if (item != null)LightSourceItems.Remove(item);}private void MoveUp(LightSourceFilterItem item){var index = LightSourceItems.IndexOf(item);if (index > 0)LightSourceItems.Move(index, index - 1);}private void MoveDown(LightSourceFilterItem item){var index = LightSourceItems.IndexOf(item);if (index < LightSourceItems.Count - 1)LightSourceItems.Move(index, index + 1);}
}

💡 温馨提示
使用 ObservableCollection.Move() 可以高效地重排项,UI 会自动更新。

如果你未来打算支持拖动排序,也可以换成 ListBox + drag-and-drop 实现。


🎨 第三步:编写 XAML 界面

<UserControl x:Class="MainPro.Views.LightTypeView"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:prism="http://prismlibrary.com/"prism:ViewModelLocator.AutoWireViewModel="True"Background="AliceBlue"><StackPanel Margin="20"><!-- 添加区域 --><StackPanel Orientation="Horizontal" Margin="0,0,0,10"><TextBox Width="150"Text="{Binding NewLightSourceName, UpdateSourceTrigger=PropertyChanged}" /><Button Content="添加光源类型" Command="{Binding AddLightSourceCommand}" Margin="10,0,0,0" /></StackPanel><!-- 光源列表 --><ItemsControl ItemsSource="{Binding LightSourceItems}"><ItemsControl.ItemTemplate><DataTemplate><StackPanel Orientation="Horizontal" Margin="5"><CheckBox Content="{Binding Name}"IsChecked="{Binding IsChecked, Mode=TwoWay}" /><Button Content="" Margin="10,0,0,0"Command="{Binding DataContext.MoveUpCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"CommandParameter="{Binding}" /><Button Content="👇" Margin="5,0,0,0"Command="{Binding DataContext.MoveDownCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"CommandParameter="{Binding}" /><Button Content="" Foreground="Red" Margin="5,0,0,0"Command="{Binding DataContext.RemoveLightSourceCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"CommandParameter="{Binding}" /></StackPanel></DataTemplate></ItemsControl.ItemTemplate></ItemsControl></StackPanel>
</UserControl>

🔍 第四步:效果展示

✅ 添加新项后立即出现在下方
❌ 删除指定项
🔼🔽 可调整顺序,数据集合自动更新 UI
在这里插入图片描述


📝 总结

这个小型项目展示了:

  • 如何结合 ObservableCollectionItemsControl 构建交互式列表
  • 如何用 Prism 的 DelegateCommand<T> 实现项级操作
  • 使用 MVVM 保持代码整洁、解耦、易维护

这种思路不仅适用于光源类型管理,也适合于任何需要用户自定义数据项列表的场景。


📎 如需源码或进一步扩展功能(如拖拽排序、持久化到配置文件等),欢迎留言!如果这篇文章对你有帮助,欢迎收藏+转发 ❤️

http://www.lryc.cn/news/2403598.html

相关文章:

  • MCU_IO驱动LED
  • 上门预约行业技术方案全解析:小程序、App还是H5?如何选择?
  • Java 集合面试题 PDF 及常见考点解析与备考指南
  • Java 大视界 -- 基于 Java 的大数据分布式计算在蛋白质组学数据分析中的加速与优化(255)
  • 如何通过外网访问内网?哪个方案比较好用?跨网远程连接网络知识早知道
  • Vue.js教学第十八章:Vue 与后端交互(二):Axios 拦截器与高级应用
  • C#中datagridview单元格value为{}大括号
  • 46、web实验-遍历数据与页面bug修改
  • 华为OD机试_2025 B卷_数组去重和排序(Python,100分)(附详细解题思路)
  • 云计算 Linux Rocky day03(which、快捷键、mount、家目录、ls、alias、mkdir、rm、mv、cp、grep)
  • gh hugging face使用
  • SQL Server全局搜索:在整个数据库中查找特定值的高效方法
  • JVM 内存溢出 详解
  • Qt 5.12 上读取 .xlsx 文件(Windows 平台)
  • 虚拟机CentOS 7 网络连接显示“以太网(ens33,被拔出)“、有线已拔出、CentOS7不显示网络图标
  • Tailwind CSS 实战:基于 Kooboo 构建 AI 对话框页面(六):图片上传交互功能
  • 传统的将自然语言转化为嵌入向量的核心机制是:,将离散的语言符号转化为连续的语义向量,其核心依赖“上下文决定语义”的假设和神经网络的特征提取能力。
  • 【前端】每日一道面试题6:解释Promise.any和Promise.allSettled的使用场景及区别。
  • wordpress+woocommerce电商平台搭建方案的优势分析
  • 玄机-日志分析-IIS日志分析
  • IDEA:配置 Git 需要完成 Git 路径设置、账号认证以及仓库关联三个主要步骤
  • PHP 复制商品扩展实操:轻松切换一号通、99api ,实现商品复制功能
  • 【办公类-104-01】20250606通义万相50分一天用完,通义万相2.1专业版测试
  • Prompt Engineering Notes
  • C++课设:学生成绩管理系统
  • 制作个人Github学术主页
  • 【Linux内核】设备模型之udev技术详解
  • FineReport模板认证找不到模板
  • STM32实战:数字音频播放器开发指南
  • 豆包和deepseek 元宝 百度ai区别是什么