perf: wpf属性监听简化 (#12725)

* perf: 绑定合并

* perf: 循环依赖检查

* perf: 循环依赖检查
This commit is contained in:
status102
2025-06-07 10:43:17 +08:00
committed by GitHub
parent 1dd3c30dc1
commit f92c4d874a
3 changed files with 94 additions and 1 deletions

View File

@@ -0,0 +1,33 @@
// <copyright file="PropertyDependsOnAttribute.cs" company="MaaAssistantArknights">
// MaaWpfGui - A part of the MaaCoreArknights project
// Copyright (C) 2021 MistEO and Contributors
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License v3.0 only as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY
// </copyright>
#nullable enable
using System;
namespace MaaWpfGui.Utilities;
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
public class PropertyDependsOnAttribute : Attribute
{
public PropertyDependsOnAttribute(string propertyName)
{
PropertyNames = [propertyName];
}
public PropertyDependsOnAttribute(string propertyName, params string[] propertyNames)
{
PropertyNames = [propertyName, .. propertyNames];
}
public string[] PropertyNames { get; init; }
}

View File

@@ -12,8 +12,13 @@
// </copyright>
#nullable enable
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using MaaWpfGui.Main;
using MaaWpfGui.Services;
using MaaWpfGui.Utilities;
using Newtonsoft.Json.Linq;
using Stylet;
@@ -21,6 +26,60 @@ namespace MaaWpfGui.ViewModels;
public abstract class TaskViewModel : PropertyChangedBase
{
private readonly Dictionary<string, List<string>> _propertyDependencies = []; // 属性依赖关系, key为被订阅的属性名, value为依赖于该属性的属性名列表
protected TaskViewModel()
{
InitializePropertyDependencies();
}
/// <summary>
/// 初始化属性依赖关系
/// </summary>
private void InitializePropertyDependencies()
{
var type = GetType();
var properties = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
foreach (var property in properties)
{
var dependsOnAttributes = property.GetCustomAttributes<PropertyDependsOnAttribute>(true);
foreach (var attribute in dependsOnAttributes.Where(i => i.PropertyNames.Length > 0))
{
foreach (var key in attribute.PropertyNames)
{
if (!_propertyDependencies.TryGetValue(key, out var value))
{
value = [];
_propertyDependencies[key] = value;
}
if (_propertyDependencies.TryGetValue(property.Name, out var values) && values.Contains(key))
{
throw new ArgumentException($"属性 {key} 依赖于属性 {property.Name}, 但它们之间存在循环依赖关系");
}
value.Add(property.Name);
}
}
}
PropertyChanged += OnPropertyChanged;
}
private void OnPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (string.IsNullOrEmpty(e.PropertyName) || !_propertyDependencies.TryGetValue(e.PropertyName, out var value))
{
return;
}
foreach (var dependentProperty in value)
{
NotifyOfPropertyChange(dependentProperty);
}
}
public virtual void ProcSubTaskMsg(AsstMsg msg, JObject details)
{
}

View File

@@ -22,6 +22,7 @@ using MaaWpfGui.Helper;
using MaaWpfGui.Models;
using MaaWpfGui.Models.AsstTasks;
using MaaWpfGui.Services;
using MaaWpfGui.Utilities;
using MaaWpfGui.Utilities.ValueType;
using MaaWpfGui.ViewModels.UI;
using Microsoft.Win32;
@@ -317,11 +318,11 @@ public class InfrastSettingsUserControlModel : TaskViewModel
CustomInfrastFile = @"resource\custom_infrast\" + value;
}
NotifyOfPropertyChange(nameof(IsCustomInfrastFileReadOnly));
ConfigurationHelper.SetValue(ConfigurationKeys.DefaultInfrast, value);
}
}
[PropertyDependsOn(nameof(DefaultInfrast))]
public bool IsCustomInfrastFileReadOnly => _defaultInfrast != UserDefined;
private bool _dormFilterNotStationedEnabled = Convert.ToBoolean(ConfigurationHelper.GetValue(ConfigurationKeys.DormFilterNotStationedEnabled, bool.TrueString));