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

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

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

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

🏗️ 第一步:定义模型类

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

csharp 复制代码
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 是整个逻辑核心,包括添加、删除、排序命令。

csharp 复制代码
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 界面

xml 复制代码
<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 保持代码整洁、解耦、易维护

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


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

相关推荐
lindexi3 小时前
WPF 引用 ASP.NET Core 的 AOT 版本
wpf·asp.netcore
我好喜欢你~19 小时前
WPF---数据模版
wpf
hqwest2 天前
C#WPF实战出真汁07--【系统设置】--菜品类型设置
开发语言·c#·wpf·grid设计·stackpanel布局
hqwest2 天前
C#WPF实战出真汁08--【消费开单】--餐桌面板展示
c#·wpf·ui设计·wpf界面设计
orangapple2 天前
WPF 打印报告图片大小的自适应(含完整示例与详解)
c#·wpf
三千道应用题3 天前
WPF&C#超市管理系统(6)订单详情、顾客注册、商品销售排行查询和库存提示、LiveChat报表
开发语言·c#·wpf
✎ ﹏梦醒͜ღ҉繁华落℘4 天前
开发WPF项目时遇到的问题总结
wpf
hqwest5 天前
C#WPF实战出真汁06--【系统设置】--餐桌类型设置
c#·.net·wpf·布局·分页·命令·viewmodel
Vae_Mars5 天前
WPF中使用InputBindings进行快捷键绑定
wpf
hqwest5 天前
C#WPF实战出真汁05--左侧导航
开发语言·c#·wpf·主界面·窗体设计·视图viewmodel