Avalonia中DataGrid内按钮的命令绑定问题求助
问题:Avalonia DataGrid内按钮命令绑定触发AVLN2000错误
在Avalonia框架开发中,普通按钮的命令绑定功能正常,但为DataGrid内的按钮绑定AddRowCommand时触发AVLN2000错误,提示无法在aa3.ViewModels.Item类型上解析名为'AddRowCommand'的属性或方法,即使移除方法参数仍报错。
相关代码
XAML代码
<Window xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:vm="clr-namespace:aa3.ViewModels" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="aa3.Views.MainWindow" x:DataType="vm:MainWindowViewModel" Icon="/Assets/avalonia-logo.ico" Title="aa3"> <Window.DataContext> <vm:MainWindowViewModel /> </Window.DataContext> <Grid> <StackPanel Orientation="Vertical" Margin="0" HorizontalAlignment="Left"> <Button Content="btn01" Width="50" Height="30" Margin="0,0,0,0" Command="{Binding SomeCommand}"/> <Button Content="btn02" Width="50" Height="30" Margin="0,0,0,0" Command="{Binding AnotherCommand}"/> <Button Content="btn03" Width="50" Height="30" Margin="0,0,0,0"/> <DataGrid ItemsSource="{Binding Items}" AutoGenerateColumns="False" Margin="20" IsReadOnly="True" CanUserReorderColumns="True" CanUserResizeColumns="True" CanUserSortColumns="False" GridLinesVisibility="All" BorderThickness="1" BorderBrush="Gray"> <DataGrid.Columns> <DataGridTextColumn Header="First Name" Binding="{Binding Number}"/> <DataGridTextColumn Header="Last Name" /> <DataGridTemplateColumn Header="Action" Width="*"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <Button Content="Add Row" Command="{Binding AddRowCommand}"/> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid> </StackPanel> </Grid> </Window>
ViewModel代码
public partial class MainWindowViewModel : ObservableObject { public ObservableCollection<Item> Items { get; set; } private int Counter { get; set; } = 1; public MainWindowViewModel() { Items = new ObservableCollection<Item> { new Item(Counter++), new Item(Counter++) }; AddRowCommand = new RelayCommand<Object>(AddRow); SomeCommand = new RelayCommand(SomeAction); AnotherCommand = new RelayCommand<Object>(AnotherAction); } public IRelayCommand AddRowCommand { get; } private void AddRow(Object currentItem) { Item item = currentItem as Item; if (item == null) { Trace.WriteLine("error"); return; } var index = Items.IndexOf(item); Items.Insert(index + 1, new Item (Counter++)); } public IRelayCommand SomeCommand { get; } private void SomeAction() { Trace.WriteLine("Some command"); } public IRelayCommand AnotherCommand { get; } private void AnotherAction(Object obj) { Trace.WriteLine("Another command"); } } public class Item : ObservableObject { public Item (int n) { Number = n; } public int Number { get; set; } }
解决方案
错误核心原因:DataGrid的CellTemplate内部的DataContext是Items集合中的单个Item实例,而AddRowCommand定义在父级的MainWindowViewModel中,直接绑定会去Item类中查找该命令,导致找不到报错。
修改按钮的命令绑定,通过RelativeSource找到父级DataGrid的DataContext,从而访问到MainWindowViewModel中的命令,同时传递当前Item作为参数:
修改后的DataTemplate代码:
<DataTemplate> <Button Content="Add Row" Command="{Binding DataContext.AddRowCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}" CommandParameter="{Binding .}"/> </DataTemplate>
如果需要类型安全的绑定,可以给DataTemplate指定x:DataType:
<DataTemplate x:DataType="vm:Item"> <Button Content="Add Row" Command="{Binding DataContext.AddRowCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}" CommandParameter="{Binding .}"/> </DataTemplate>
修改后,按钮会正确绑定到MainWindowViewModel中的AddRowCommand,并将当前行的Item对象作为参数传递给命令方法,解决AVLN2000错误。
内容的提问来源于stack exchange,提问作者oao
相关产品推荐
相关产品推荐

