学无先后达者为师!
不忘初心,砥砺前行。

Avalonia 如何在 ItemsControl 中绑定 MainViewModel 中的 Command?

当需要在 Avalonia 中展示一个列表时,ItemsControl 是一个不错的选择。如果需要针对列表中的某一项进行操作,通常不会在 ItemModel 中进行实现,而是放入列表所在的 ViewModel 中:

public class ItemModel
{
    public ItemModel(string name)
    {
        this.Name = name;
    }
    public string Name { get; }
}
using CommunityToolkit.Mvvm.Input;
using System.Collections.ObjectModel;

public partial class MainViewModel : ViewModelBase
{
    public ObservableCollection Items { get; } = new ObservableCollection();

    public MainViewModel()
    {
        for (int i = 0; i < 50; i++)
        {
            this.Items.Add(new ItemModel("Item " + (i + 1)));
        }
    }

    [RelayCommand]
    private void Delete(ItemModel item)
    {
        this.Items.Remove(item);
    }
}

后端代码并不复杂,但下面的界面代码会导致编译失败:


                    

报错信息如下:

Unable to resolve property or method of name ‘DeleteCommand’ on type ‘ItemsPanelMainCommand.ViewModels.ItemModel’.

AVLN:0004

这是因为进入 ItemsControl 后,控件的 DataContext 被设置为了 ItemModel 的实例,而 ItemModel 本身是不存在 DeleteCommand 的,要想办法找到外层的 MainViewModel 才行。

解决方法



上面提供了三种方案大同小异:都是通过找到父级的数据上下文然后调用父级控件上下文的 DeleteCommand 。主要区别是:在处理编译绑定时使用了不同的策略。

  • 方案 1 为控件附加了一个 x:CompileBindings 属性,并设置值为 False,以此来抑制编译绑定的检查从而保证编译成功。
  • 方案 2 直接使用了 ReflectionBinding ,即“反射绑定”。这种绑定方式也不进行编译检查。
  • 方案 3 在拿到父级的 DataContext 之后进行了显示的类型转换,确保类型正确后编译通过。

总结

本文所述的代码虽然简单,但也是新手入门期间大概率会碰上的问题。作为一名开发人员,我更倾向于使用第三种方式。本文所示代码已经上传,可以在以下地址查看:

https://gitee.com/coderbusy/demo/tree/master/avaloina/ItemsPanelMainCommand

赞(6) 打赏
未经允许不得转载:码农很忙 » Avalonia 如何在 ItemsControl 中绑定 MainViewModel 中的 Command?

评论 抢沙发

给作者买杯咖啡

非常感谢你的打赏,我们将继续给力更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫

微信扫一扫

登录

找回密码

注册