2
votes

I'm doing my first app using MVVM. I have in "View" declared Datagrid. Code XAML below:

            <DataGridTemplateColumn Header="delete">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Button
                            Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type> UserControl},Mode=FindAncestor}, Path=DataContext.ClickCommand}">                                 Content="X" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>> 
    </DataGrid>

In my ViewModel class I can run function that I want after click button "delete" by part of code:

    public ICommand ClickCommand => _clickCommand ?? (_clickCommand = new CommandHandler(Delete, _canExecute));
    public void Delete()
    {
     //  DataTable.Rows.RemoveAt();
    }

I have problem because I can't get index of selectet row. Source of data in datagrid is dataTable.

Do you have any ideas how to do this?

I've tried something with passing parameter with command of button but I coudn't make it works.

2
It's getting even funnier: you can select row 1 while clicking the button in row 2 - so you better not rely on the selected row for a button that exists per row.grek40

2 Answers

4
votes

Xmal code

<Button Command="{Binding Path=DataContext.ViewCommand,RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" CommandParameter="{Binding Id}" Content="X" Background="Chocolate"/>

Codebehind code

 public RelayCommand DeleteCommand
 {
    get
     {
        return new RelayCommand(p => Delete(p));
     }
 }

public void Delete(string id)
{
 //  DataTable.Rows.RemoveAt();
}

This is example you can pass whatever you want in that cmd parameter.

Relay cmd

public class RelayCommand : ICommand
{
    private Action<object> action;
    private Func<bool> canFuncPerform;
    public event EventHandler CanExecuteChanged;
    public RelayCommand(Action<object> executeMethod)
    {
        action = executeMethod;
    }
    public RelayCommand(Action<object> executeMethod, Func<bool> canExecuteMethod)
    {
        action = executeMethod;
        canFuncPerform = canExecuteMethod;
    }
    public void RaiseCanExecuteChanged()
    {
        CanExecuteChanged(this, EventArgs.Empty);
    }
    public bool CanExecute(object parameter)
    {
        if (canFuncPerform != null)
        {
            return canFuncPerform();
        }

        if (action != null)
        {
            return true;
        }

        return false;
    }


    public void Execute(object parameter)
    {
        if (action != null)
        {
            action(parameter);                
        }
    }
}
2
votes

You shouldn't rely on the selected item. Instead pass the current row item as CommandParameter:

<DataGridTemplateColumn Header="delete">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <Button
                Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl},Mode=FindAncestor}, Path=DataContext.ClickCommand}"
                CommandParameter="{Binding}"
                Content="X" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

Then of course, use an ICommand implementation that is not discarding the command parameter and use it to identify the row to be deleted.