admin管理员组文章数量:1033347
Avalonia UI 如何在 ItemsControl 中绑定 MainViewModel 中的 Command?
当需要在 Avalonia UI 中展示一个列表时,ItemsControl 组件是一个不错的选择。如果需要针对列表中的某一项进行操作,通常不会在 ItemModel 中进行实现,而是放入列表所在的 ViewModel 中:
代码语言:javascript代码运行次数:0运行复制public class ItemModel
{
public ItemModel(string name)
{
this.Name = name;
}
public string Name { get; }
}
代码语言:javascript代码运行次数:0运行复制using CommunityToolkit.Mvvm.Input;
using System.Collections.ObjectModel;
public partial class MainViewModel : ViewModelBase
{
public ObservableCollection<ItemModel> Items { get; } = new ObservableCollection<ItemModel>();
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);
}
}
后端代码并不复杂,但下面的界面代码会导致编译失败:
代码语言:javascript代码运行次数:0运行复制<UserControl xmlns=";
xmlns:x=";
xmlns:d=";
xmlns:mc=";
xmlns:vm="clr-namespace:ItemsPanelMainCommand.ViewModels"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="ItemsPanelMainCommand.Views.MainView"
x:DataType="vm:MainViewModel">
<Design.DataContext>
<vm:MainViewModel />
</Design.DataContext>
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{ Binding Name}"></TextBlock>
<Button Command="{Binding DeleteCommand}" CommandParameter="{Binding}">删除</Button>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</UserControl>
报错信息如下:
Unable to resolve property or method of name ‘DeleteCommand’ on type ‘ItemsPanelMainCommand.ViewModels.ItemModel’. AVLN:0004
这是因为进入 ItemsControl 后, 控件的 DataContext 被设置为了 ItemModel 的实例,而 ItemModel 本身是不存在 DeleteCommand 的,要想办法找到外层的 MainViewModel 才行。
解决方法
代码语言:javascript代码运行次数:0运行复制<Button Command="{Binding $parent[ItemsControl].DataContext.DeleteCommand}" x:CompileBindings="False" CommandParameter="{ Binding}">删除-方案1</Button>
<Button Command="{ReflectionBinding $parent[ItemsControl].DataContext.DeleteCommand}" CommandParameter="{Binding}">删除-方案2</Button>
<Button Command="{Binding $parent[ItemsControl].((vm:MainViewModel)DataContext).DeleteCommand }" CommandParameter="{Binding}">删除-方案3</Button>
上面提供了三种方案大同小异:都是通过找到父级的数据上下文然后调用父级控件上下文的 DeleteCommand 。主要区别是:在处理编译绑定时使用了不同的策略。
- 方案 1 为控件附加了一个 x:CompileBindings 属性,并设置值为 False,以此来抑制编译绑定的检查从而保证编译成功。
- 方案 2 直接使用了 ReflectionBinding ,即“反射绑定”。这种绑定方式也不进行编译检查。
- 方案 3 在拿到父级的 DataContext 之后进行了显示的类型转换,确保类型正确后编译通过。
总结
本文所述的代码虽然简单,但也是新手入门期间大概率会碰上的问题。作为一名开发人员,我更倾向于使用第三种方式。
Avalonia UI 如何在 ItemsControl 中绑定 MainViewModel 中的 Command?
当需要在 Avalonia UI 中展示一个列表时,ItemsControl 组件是一个不错的选择。如果需要针对列表中的某一项进行操作,通常不会在 ItemModel 中进行实现,而是放入列表所在的 ViewModel 中:
代码语言:javascript代码运行次数:0运行复制public class ItemModel
{
public ItemModel(string name)
{
this.Name = name;
}
public string Name { get; }
}
代码语言:javascript代码运行次数:0运行复制using CommunityToolkit.Mvvm.Input;
using System.Collections.ObjectModel;
public partial class MainViewModel : ViewModelBase
{
public ObservableCollection<ItemModel> Items { get; } = new ObservableCollection<ItemModel>();
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);
}
}
后端代码并不复杂,但下面的界面代码会导致编译失败:
代码语言:javascript代码运行次数:0运行复制<UserControl xmlns=";
xmlns:x=";
xmlns:d=";
xmlns:mc=";
xmlns:vm="clr-namespace:ItemsPanelMainCommand.ViewModels"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="ItemsPanelMainCommand.Views.MainView"
x:DataType="vm:MainViewModel">
<Design.DataContext>
<vm:MainViewModel />
</Design.DataContext>
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{ Binding Name}"></TextBlock>
<Button Command="{Binding DeleteCommand}" CommandParameter="{Binding}">删除</Button>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</UserControl>
报错信息如下:
Unable to resolve property or method of name ‘DeleteCommand’ on type ‘ItemsPanelMainCommand.ViewModels.ItemModel’. AVLN:0004
这是因为进入 ItemsControl 后, 控件的 DataContext 被设置为了 ItemModel 的实例,而 ItemModel 本身是不存在 DeleteCommand 的,要想办法找到外层的 MainViewModel 才行。
解决方法
代码语言:javascript代码运行次数:0运行复制<Button Command="{Binding $parent[ItemsControl].DataContext.DeleteCommand}" x:CompileBindings="False" CommandParameter="{ Binding}">删除-方案1</Button>
<Button Command="{ReflectionBinding $parent[ItemsControl].DataContext.DeleteCommand}" CommandParameter="{Binding}">删除-方案2</Button>
<Button Command="{Binding $parent[ItemsControl].((vm:MainViewModel)DataContext).DeleteCommand }" CommandParameter="{Binding}">删除-方案3</Button>
上面提供了三种方案大同小异:都是通过找到父级的数据上下文然后调用父级控件上下文的 DeleteCommand 。主要区别是:在处理编译绑定时使用了不同的策略。
- 方案 1 为控件附加了一个 x:CompileBindings 属性,并设置值为 False,以此来抑制编译绑定的检查从而保证编译成功。
- 方案 2 直接使用了 ReflectionBinding ,即“反射绑定”。这种绑定方式也不进行编译检查。
- 方案 3 在拿到父级的 DataContext 之后进行了显示的类型转换,确保类型正确后编译通过。
总结
本文所述的代码虽然简单,但也是新手入门期间大概率会碰上的问题。作为一名开发人员,我更倾向于使用第三种方式。
本文标签: Avalonia UI 如何在 ItemsControl 中绑定 MainViewModel 中的 Command
版权声明:本文标题:Avalonia UI 如何在 ItemsControl 中绑定 MainViewModel 中的 Command? 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://it.en369.cn/jiaocheng/1748035821a2244702.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论