前端开发入门到精通的在线学习网站

网站首页 > 资源文章 正文

CommunityToolkit.Mvvm:ObservableProperty 属性生成器深度解析

qiguaw 2025-03-11 20:30:53 资源文章 91 ℃ 0 评论

什么是ObservableProperty?

ObservableProperty是CommunityToolkit.Mvvm提供的一个强大属性生成器,它能够:

  • 自动生成属性变更通知
  • 减少样板代码
  • 提供编译时代码生成
  • 支持复杂的属性变更逻辑

安装准备

# 通过NuGet安装
dotnet add package CommunityToolkit.Mvvm

详细示例集锦

示例1:基础用户信息管理

// 用户信息ViewModel
public partial class UserViewModel : ObservableObject
{
    // 基础属性定义
    [ObservableProperty]
    private string _username;

    [ObservableProperty]
    private int _age;

    [ObservableProperty]
    private string _email;

    // 自定义属性变更处理
    partial void OnUsernameChanged(string value)
    {
        // 用户名变更时自动生成邮箱
        if (!string.IsNullOrWhiteSpace(value))
        {
            Email = $"{value.ToLower().Replace(" ", "")}@example.com";
        }
    }

    // 验证方法
    private bool ValidateUserInfo()
    {
        // 简单的输入验证逻辑
        return !string.IsNullOrWhiteSpace(Username)
               && Age > 0
               && !string.IsNullOrWhiteSpace(Email);
    }
}

public partial class Form1 : Form
{
    private UserViewModel _viewModel;
    public Form1()
    {
        InitializeComponent();

        // 初始化ViewModel
        _viewModel = new UserViewModel();

        // 数据绑定
        txtUsername.DataBindings.Add("Text", _viewModel, nameof(UserViewModel.Username), true, DataSourceUpdateMode.OnPropertyChanged);
        numAge.DataBindings.Add("Value", _viewModel, nameof(UserViewModel.Age), true, DataSourceUpdateMode.OnPropertyChanged);
        txtEmail.DataBindings.Add("Text", _viewModel, nameof(UserViewModel.Email), true, DataSourceUpdateMode.OnPropertyChanged);

    }

    private void btnShow_Click(object sender, EventArgs e)
    {
        // 序列化ViewModel对象
        MessageBox.Show(JsonSerializer.Serialize(_viewModel)); 
    }
}

示例2:复杂设置管理器

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace App05
{
    public partial class ApplicationSettingsViewModel : ObservableValidator
    {
        // 主题设置
        [ObservableProperty]
        [NotifyCanExecuteChangedFor(nameof(ApplyThemeCommand))]
        private string _currentTheme = "Light";

        // 音量设置,使用验证特性  
        [ObservableProperty]
        [Range(0, 100, ErrorMessage = "音量必须在0-100之间")]
        private int _soundVolume = 50;

        // 通知设置
        [ObservableProperty]
        private bool _enableNotifications = true;

        // 应用主题命令
        [RelayCommand(CanExecute = nameof(CanApplyTheme))]
        private void ApplyTheme()
        {
            // 实际应用主题的逻辑
            MessageBox.Show($"应用主题:{CurrentTheme}");
        }

        // 命令执行条件
        private bool CanApplyTheme() =>
            !string.IsNullOrEmpty(CurrentTheme);

        // 音量变更处理
        partial void OnSoundVolumeChanged(int value)
        {
            // 音量变更的额外逻辑
            Console.WriteLine($"音量已调整为:{value}");
        }
    }
}

public partial class Form2 : Form
{
    private ApplicationSettingsViewModel _viewModel;

    public Form2()
    {
        InitializeComponent();

        // 设置主题下拉框的数据源  
        cboTheme.Items.AddRange(new string[] { "Light", "Dark", "System" });

        _viewModel = new ApplicationSettingsViewModel();

        // 主题下拉绑定  
        cboTheme.DataBindings.Add("SelectedItem", _viewModel,
            nameof(ApplicationSettingsViewModel.CurrentTheme),
            true, DataSourceUpdateMode.OnPropertyChanged);

        // 音量滑动条绑定  
        trackVolume.DataBindings.Add("Value", _viewModel,
            nameof(ApplicationSettingsViewModel.SoundVolume),
            true, DataSourceUpdateMode.OnPropertyChanged);

        // 通知复选框绑定  
        chkEnableNotifications.DataBindings.Add("Checked", _viewModel,
            nameof(ApplicationSettingsViewModel.EnableNotifications),
            true, DataSourceUpdateMode.OnPropertyChanged);


        // 添加音量变更事件  
        trackVolume.ValueChanged += TrackVolume_ValueChanged;

        // 添加应用主题按钮点击事件  
        btnApplyTheme.Click += BtnApplyTheme_Click;

    }

    private void TrackVolume_ValueChanged(object sender, EventArgs e)
    {
        // 更新音量标签  
        lblVolumeValue.Text = $"音量: {trackVolume.Value}%";
    }

    private void BtnApplyTheme_Click(object sender, EventArgs e)
    {
        // 调用ViewModel的应用主题命令  
        _viewModel.ApplyThemeCommand.Execute(null);
    }
}

示例3:库存管理系统

// 商品模型
public partial class Product : ObservableValidator
{
    [ObservableProperty]
    private string _productId;

    [ObservableProperty]
    private string _name;

    [ObservableProperty]
    [Range(0, double.MaxValue)]
    private decimal _price;

    [ObservableProperty]
    [Range(0, int.MaxValue)]
    private int _stockQuantity;

    // 价格变更处理
    partial void OnPriceChanged(decimal value)
    {
        if (value < 0)
        {
            Price = 0;
        }
    }
}

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace App05
{
    // 库存管理ViewModel
    public partial class InventoryViewModel : ObservableObject
    {
        // 商品列表
        [ObservableProperty]
        private ObservableCollection _products = new();

        // 当前选中商品
        [ObservableProperty]
        private Product _selectedProduct;

        // 总库存价值
        [ObservableProperty]
        private decimal _totalInventoryValue;

        // 添加商品命令
        [RelayCommand]
        private void AddProduct()
        {
            var newProduct = new Product
            {
                ProductId = Guid.NewGuid().ToString(),
                Name = "新商品",
                Price = 1,
                StockQuantity = 2
            };
            Products.Add(newProduct);
            SelectedProduct = newProduct;
            RecalculateTotalValue();
        }

        // 删除商品命令
        [RelayCommand(CanExecute = nameof(CanDeleteProduct))]
        private void DeleteProduct()
        {
            if (SelectedProduct != null)
            {
                Products.Remove(SelectedProduct);
                RecalculateTotalValue();
            }
        }

        // 删除命令的执行条件
        private bool CanDeleteProduct() => SelectedProduct != null;

        // 计算总库存价值
        private void RecalculateTotalValue()
        {
            TotalInventoryValue = Products.Sum(p => p.Price * p.StockQuantity);
        }
    }
}

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace App05
{
    public partial class Form3 : Form
    {
        private InventoryViewModel _viewModel;
 
        public Form3()
        {
            InitializeComponent();

            // 禁用新行  
            dgvProducts.AllowUserToAddRows = false;

            // 如果没有数据则不显示空行  
            dgvProducts.DataSource = null;

            BindingSource _productBindingSource = new BindingSource();

            // 创建BindingSource  
            _productBindingSource = new BindingSource();

            _viewModel = new InventoryViewModel();

            // 将BindingSource绑定到ViewModel的Products集合  
            _productBindingSource.DataSource = _viewModel.Products;

            // 设置DataGridView的数据源为BindingSource  
            dgvProducts.DataSource = _productBindingSource;

            // 配置DataGridView列  
            ConfigureDataGridViewColumns();

            // 绑定总库存价值  
            lblTotalValue.DataBindings.Add("Text", _viewModel,
                nameof(InventoryViewModel.TotalInventoryValue),
                true,
                DataSourceUpdateMode.OnPropertyChanged,
                "总库存价值:{0:C2}");

            // 订阅ViewModel的Products集合变更事件  
            _viewModel.Products.CollectionChanged += (s, e) =>
            {
                // 刷新BindingSource  
                _productBindingSource.ResetBindings(false);
            };
        }
        private void ConfigureDataGridViewColumns()
        {
            dgvProducts.Columns.Clear();
            dgvProducts.AutoGenerateColumns = false;

            // 商品ID列  
            var idColumn = new DataGridViewTextBoxColumn
            {
                DataPropertyName = "ProductId",
                HeaderText = "商品ID",
                Name = "ProductId",
                Width = 150
            };
            dgvProducts.Columns.Add(idColumn);

            // 商品名称列  
            var nameColumn = new DataGridViewTextBoxColumn
            {
                DataPropertyName = "Name",
                HeaderText = "商品名称",
                Name = "Name",
                Width = 150
            };
            dgvProducts.Columns.Add(nameColumn);

            // 单价列  
            var priceColumn = new DataGridViewTextBoxColumn
            {
                DataPropertyName = "Price",
                HeaderText = "单价",
                Name = "Price",
                ValueType = typeof(decimal),
                Width = 100
            };
            dgvProducts.Columns.Add(priceColumn);

            // 库存数量列  
            var quantityColumn = new DataGridViewTextBoxColumn
            {
                DataPropertyName = "StockQuantity",
                HeaderText = "库存数量",
                Name = "StockQuantity",
                ValueType = typeof(int),
                Width = 100
            };
            dgvProducts.Columns.Add(quantityColumn);
        }

        private void btnAdd_Click(object sender, EventArgs e)
        {
            // 执行添加商品命令  
            _viewModel.AddProductCommand.Execute(null);
        }

        private void dgvProducts_SelectionChanged(object sender, EventArgs e)
        {
            // 更新选中商品  
            if (dgvProducts.CurrentRow != null)
            {
                _viewModel.SelectedProduct = dgvProducts.CurrentRow.DataBoundItem as Product;
            }
        }

        private void btnDelete_Click(object sender, EventArgs e)
        {
            _viewModel.DeleteProductCommand.Execute(null);
        }
    }
}

结论

ObservableProperty是现代.NET开发中简化MVVM模式的利器。通过自动生成属性变更通知,它显著减少了样板代码,提高了开发效率。

如果你正在从事上位机、自动化、机器视觉、物联网(IOT)项目或数字化转型方面的工作,欢迎加入我的圈子!在这里,我们不仅可以轻松畅聊最新技术动态和行业趋势,还能够在技术问题上互相帮助和支持。我会尽量利用我的知识和经验来帮助你解决问题,当然也期待从大家的专业见解中学习和成长。无论你是新手还是老鸟,期待与志同道合的朋友交流心得,一起进步!私信给我!

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表