I am stuck here and I can not find anything similar!! In a WPF application and Community MVVM Toolkit, I have

DashBoard.xaml

<Window x:Class="MyIatreio.MVVM.Views.DashBoard"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:local="clr-namespace:MyIatreio.MVVM.Views"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:nacontrols="clr-namespace:MyIatreio.NAControls"
        xmlns:viewmodels="clr-namespace:MyIatreio.MVVM.ViewModels"
        xmlns:converters="clr-namespace:MyIatreio.MVVM.Converters"
        Title="DashBoard"
        Width="800"
        Height="450"
        d:DataContext="{d:DesignInstance Type=viewmodels:DashBoardViewModel}"
        Loaded="Window_Loaded"
        ShowInTaskbar="False"
        WindowState="Maximized"
        WindowStartupLocation="CenterScreen"
        mc:Ignorable="d">

    <Window.Resources>
        <converters:DataGridRowToVisitConverter x:Key="DataGridRowToVisit" />
    </Window.Resources>
 
    <Grid>

        <DataGrid x:Name="VisitsDataGrid"
                  AutoGenerateColumns="True"
                  CanUserAddRows="False"
                  IsReadOnly="True"
                  IsSynchronizedWithCurrentItem="True"
                  ItemsSource="{Binding Visits, Mode=TwoWay}"
                  SelectedItem="{Binding SelectedVisit, Mode=TwoWay}"
                  SelectionChanged="VisitsDataGrid_SelectionChanged"
                  SelectionMode="Single"
                  DataContext="{Binding}">

            <DataGrid.Resources>
                <ContextMenu x:Key="RowContextMenu">
                    <MenuItem Header="Edit" Command="{Binding EditVisitCommand}"
                              CommandParameter="{Binding SelectedItem, 
                        RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
                    <!--  Your ContextMenu Items  -->
                </ContextMenu>
            </DataGrid.Resources>

            <DataGrid.RowStyle>
                <Style TargetType="DataGridRow">
                    <Setter Property="ContextMenu" Value="{StaticResource RowContextMenu}" />
                </Style>
            </DataGrid.RowStyle>
        </DataGrid>

    </Grid>
</Window>

DashBoard.xaml.cs

using CommunityToolkit.Mvvm.Messaging;
using Microsoft.EntityFrameworkCore.Diagnostics;
using MyIatreio.MVVM.Messages;
using MyIatreio.MVVM.Models;
using MyIatreio.MVVM.ViewModels;
using MyIatreio.Utils.Dialogs;
using Syncfusion.Data.Extensions;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;

namespace MyIatreio.MVVM.Views;

public partial class DashBoard : Window
{
    private readonly DashBoardViewModel _dashboardViewModel;

    public DashBoard()
    {
        InitializeComponent();

        _dashboardViewModel = new DashBoardViewModel();

        DataContext = _dashboardViewModel;
    }

    private void Close_Clicked(object sender, RoutedEventArgs e)
    {
        this.Close();
    }

    private async void Window_Loaded(object sender, RoutedEventArgs e)
    {
        await _dashboardViewModel.LoadData();
    }

    // etc !!
}

and in DashBoardViewModel.cs

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.EntityFrameworkCore;
using MyIatreio.DataAccess;
using MyIatreio.DataAccess.Context;
using MyIatreio.DataAccess.Repositories;
using MyIatreio.MVVM.Messages;
using MyIatreio.MVVM.Models;
using MyIatreio.MVVM.Views;
using Syncfusion.DocIO.DLS;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Windows.Controls;
using System.Windows.Input;

namespace MyIatreio.MVVM.ViewModels;

public partial class DashBoardViewModel : ObservableRecipient
{
    private readonly UnitOfWork _uoW;

    // SelectedVisit
    [ObservableProperty]
    private Visit _selectedVisit;

    [ObservableProperty]
    private int _visitsCount;

    [ObservableProperty]
    private ObservableCollection<Visit> _visits;


    public DashBoardViewModel()
    {
        SelectedVisit = new Visit();

        _uoW = new(new AppDbContext());

        Visits = [];
    }



    // EditVisit command with param either Visit selectedVisit or Object obj 
    // any of the following is accepted
    //
    // public void EditVisit(Visit visit)
    // public void EditVisit(Object obj)
    [RelayCommand]
    public void EditVisit(Object obj)
    {
        Visit selectedVisit = (Visit)obj;

        if (selectedVisit == null) return;

        // etc
    }

    [RelayCommand]
    private void DeleteVisit(Visit visit)
    {
        Visits.Remove(visit);
        _uoW.Visits.Remove(visit);
        _uoW.SaveChanges();
    }

    // etc

}

I would like to avoid using events and the code behind. I would like the viewmodel's EditVisit command to be called both when the user double clicks in a row and also when the user right clicks in a row and selects EditVisit on the ContextMenu that would popup!!

Several attempts made to manage to pass the DataGrid's selected row as a CommandParameter in the DashBoard.xaml file and send it to the viewmodel directly (not via code behind) but all failed. There must be a way to pass this selected row as a CommandParameter from within xaml only.

All I wanted from any of you WPF and Community MVVM Toolkit gurus is to guide me on how to pass the selected row (either as a Visit or as an Object) to the viewmodel

Can someone help me as I cannot find anything similar either in Google or in ChatGPT 3.5

Thanx in advance

1

There are 1 best solutions below

9
Sergio Sánchez On

You need to associate your property with your command. Try the following:

// SelectedVisit
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(EditVisit))]
private Visit _selectedVisit;

I edit my answer for a correct answer:

// SelectedVisit
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(EditVisitCommand))]
private Visit _selectedVisit;