WPF-社区 MVVM 工具包 - 将中继命令发送到 ViewModel,使用 DataGrid 的 SelectedItem 作为命令参数,避免代码隐藏事件

问题描述 投票:0回答:1

我被困在这里,找不到类似的东西! 在 WPF 应用程序和社区 MVVM 工具包中,我有

仪表板.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>

仪表板.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 !!
}

在 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

}

我想避免使用事件和背后的代码。 我希望当用户连续双击时以及当用户右键单击一行并在弹出的 ContextMenu 上选择 EditVisit 时调用 viewmodel 的 EditVisit 命令!!

多次尝试设法将 DataGrid 的选定行作为 DashBoard.xaml 文件中的 CommandParameter 传递,并将其直接发送到视图模型(不通过后面的代码),但都失败了。必须有一种方法仅从 xaml 中将此选定行作为 CommandParameter 传递。

我希望 WPF 和社区 MVVM 工具包专家能够指导我如何将选定的行(作为访问或作为对象)传递到视图模型

有人可以帮助我吗,因为我在 Google 或 ChatGPT 3.5 中都找不到类似的内容

提前谢谢

wpf datagrid relaycommand commandparameter community-toolkit-mvvm
1个回答
0
投票

您需要将您的属性与您的命令关联起来。尝试以下操作:

// SelectedVisit
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(EditVisit))]
private Visit _selectedVisit;
© www.soinside.com 2019 - 2024. All rights reserved.