Search code examples
c#avaloniauiavalonia

How to add binding to the button inside DataGrid?


I don't understand how to add binding to the button inside DataGrid. Can you please help me?

What I have: I can connect any simple button and I can give it some functionality. But when I want to do a binding to the button inside DataGrid I catch errors. Current error for the code below is AVLN2000 Unable to resolve property or method of name 'AddRowCommand' on type 'aa3.ViewModels.Item'. And without any parameter I still see a error.

My code

<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>

also the code in namespace aa3.ViewModels

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; }
}

I tried to delete all parameters from my method but it doesn't work still, also I checked the documentation of Avalonia but looks like this question is not written there.


Solution

  • I got the answer from the community of Avalonia via the https://t.me/Avalonia link.

    I needed to add into the tag Window the parameter x:Name="Root", and my command inside the button should look like:

    Command="{Binding #Root.((vm:MainWindowViewModel)DataContext).AddRowCommand}"
    

    Also, they gave me the link to the documentation, which includes instructions on how to bind a concretely named section: https://docs.avaloniaui.net/docs/guides/data-binding/binding-to-controls#binding-to-a-named-control