You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AvaloniaUI动态XAML绑定ExpandoObject属性不更新问题

解决Avalonia中动态属性绑定ExpandoObject失效的问题

问题根源

Avalonia的绑定引擎依赖静态属性元数据(反射或TypeDescriptor)解析绑定路径,而ExpandoObject的动态属性无法被该引擎正确识别,导致出现Could not find a matching property accessor错误,同时属性变更也无法被绑定系统监听。

解决方案:自定义动态属性容器

替换ExpandoObject为继承DynamicObject并实现INotifyPropertyChanged的自定义类,手动处理属性读写和变更通知,让Avalonia绑定系统能正确识别动态属性。

1. 创建自定义动态属性类

using System.ComponentModel;
using System.Dynamic;
using System.Runtime.CompilerServices;

public class DynamicPropertyBag : DynamicObject, INotifyPropertyChanged
{
    private readonly Dictionary<string, object?> _properties = new();

    public event PropertyChangedEventHandler? PropertyChanged;

    // 处理动态属性读取逻辑
    public override bool TryGetMember(GetMemberBinder binder, out object? result)
    {
        return _properties.TryGetValue(binder.Name, out result);
    }

    // 处理动态属性写入逻辑,触发变更通知
    public override bool TrySetMember(SetMemberBinder binder, object? value)
    {
        _properties[binder.Name] = value;
        OnPropertyChanged(binder.Name);
        return true;
    }

    // 提供索引器,方便绑定系统访问属性
    public object? this[string key]
    {
        get => _properties.TryGetValue(key, out var val) ? val : null;
        set
        {
            _properties[key] = value;
            OnPropertyChanged(key);
        }
    }

    private void OnPropertyChanged([CallerMemberName] string? propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

2. 更新ViewModel

将原ExpandoObject替换为自定义的DynamicPropertyBag:

using CommunityToolkit.Mvvm.ComponentModel;
using System.Diagnostics;

namespace DynamicBindingControls.ViewModels; 

public partial class DynamicSettingsGroupVM : ViewModelBase {
  [ObservableProperty]
  private string _name;
  // 替换为自定义动态属性容器
  public dynamic DynamicSettingsProperties { get; set; } = new DynamicPropertyBag();

  public DynamicSettingsGroupVM(string aName) {
    Name = aName;
    ((INotifyPropertyChanged)DynamicSettingsProperties).PropertyChanged += HandlePropertyChanges;
  }

  private void HandlePropertyChanges(object? sender, PropertyChangedEventArgs e) {
    var bag = DynamicSettingsProperties as DynamicPropertyBag;
    Trace.WriteLine($"{e.PropertyName} has changed to {bag?[e.PropertyName]}.");
  }
}

3. 调整绑定方式

使用索引器语法绑定动态属性,确保Avalonia能正确解析路径:

public void CreateDynamicSettings() {
  var myDC = DataContext as ViewModels.DynamicSettingsGroupVM;

  var props = myDC.DynamicSettingsProperties as DynamicPropertyBag;
  props["DynaProp"] = "Brand new";
  // 使用索引器语法绑定动态属性
  var settingField = new TextBox {
    [!TextBox.TextProperty] = new Binding("DynamicSettingsProperties['DynaProp']")
  };

  stpDynamicFields.Children.Add(settingField);
}

验证效果

运行应用后:

  • TextBox会正确显示初始值Brand new
  • 修改TextBox内容时,调试日志会输出属性变更信息
  • 绑定的双向同步功能正常工作

内容的提问来源于stack exchange,提问作者Eric Eggers

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.01 20:44:53