Search code examples
c#xamlmvvmwinui-3

Button Command doesn't getting executed on CommunityToolKit DataGrid


I'm using WinUI CommunityToolkit DataGrid from this nuget package. here is my data grid definition:

<toolkit:DataGrid x:Name="dataGrid"
                  ItemsSource="{x:Bind ViewModel.Tests, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                  MinHeight="500"
                  AreRowDetailsFrozen="False"
                  AreRowGroupHeadersFrozen="True"
                  AutoGenerateColumns="False"
                  CanUserSortColumns="True"
                  ColumnHeaderHeight="40"
                  FrozenColumnCount="0"
                  RowDetailsVisibilityMode="Collapsed"
                  RowGroupHeaderPropertyNameAlternative="Range">
    <toolkit:DataGrid.Columns>
        <toolkit:DataGridTemplateColumn Header="Records (count)" Tag="RecordsCount" Width="150">
            <toolkit:DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding RecordsCount}"/>
                </DataTemplate>
            </toolkit:DataGridTemplateColumn.CellTemplate>
        </toolkit:DataGridTemplateColumn>
        <toolkit:DataGridTemplateColumn  Width="184">
            <toolkit:DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
                        <!-- Click event works but command doesn't getting executed -- >
                        <Button Width="40" Height="40" 
                                Command="{Binding ViewModel.DeleteTestCommand, ElementName=testPage}"
                                CommandParameter="{Binding Id}">
                        </Button>
                        <Button Width="40" Height="40"
                                Command="{Binding ViewModel.EditTestCommand, ElementName=testPage}"
                                CommandParameter="{Binding Id}">
                        </Button>
                    </StackPanel>
                </DataTemplate>
            </toolkit:DataGridTemplateColumn.CellTemplate>
        </toolkit:DataGridTemplateColumn>
    </toolkit:DataGrid.Columns>
</toolkit:DataGrid>

here is my view model:

public partial class TestsPageViewModel : ObservableRecipient
{
    public IRelayCommand<int> EditTestCommand { get; }

    public IRelayCommand<int> DeleteTestCommand { get; }

    public TestsPageViewModel(ITestsQueryService testsQueryService, INavigationService navigationService)
    {
        EditTestCommand = new RelayCommand<int>(EditTest);
        DeleteTestCommand = new RelayCommand<int>(DeleteTest);
       
        Tests = new ObservableCollection<TestModel>(); //(Some tests here);
    }

    public void DeleteTest(int id)
    {
        //var test = Tests.First(P => P.Id == id);
    }

    public void EditTest(int id)
    {
        //var test = Tests.First(P => P.Id == id);
    }

    public ObservableCollection<TestModel> Tests 
    { 
        get => _tests;
        set => SetProperty(ref _tests, value); 
    }
}

and TestModel contains:

  • public int Id { get; set; }
  • public int RecordCount { get; set; } , ....

As I mentioned in the Xaml Click event works for buttons but Commands aren't working at all.

tnx for any help 😊


Solution

  • I guess this is a DataGrid's issue (or by design?).

    Let me show you 2 workarounds.

    A. Use the Click event:

    TestPage.xaml.cs

    private void EditButton_Click(object sender, e)
    {
        if (sender is Button button &&
            button.DataContext is TestModel testModel)
        {
            this.ViewModel.EditTestModelCommand.Execute(testModel.Id);
        }
    }
    

    B. Add a EditCommand on TestModel: TestModel.cs

    public partial class TestModel : ObservableObject
    {
        [ObservableProperty]
        private id;
    
        public ICommand EditCommand { get; init; }
    }
    

    TestViewModel.cs

    [RelayCommand]
    private void EditTestModel(int id)
    {
    }
    
    // Set the command on each models.
    TestModel model = new ()
    {
        Id = 1,
        EditCommand = EditTestModel,
    };