如何在WPF MVVM应用程序中传递DataGridCellEditEventArgs

如何在WPF MVVM应用程序中传递DataGridCellEditEventArgs,wpf,events,mvvm,datagrid,Wpf,Events,Mvvm,Datagrid,我正在开发WPF LOB应用程序,并使用Prism和委托命令将UI与视图模型分离 当用户从UI而不是从视图模型或服务对特定单元格进行更改时,我需要调用一些其他功能 我已经创建了附加的行为 public static class DataGridCellEditEndingBehaviour { private static readonly DependencyProperty CellEditEndingProperty = DependencyProperty.Reg

我正在开发WPF LOB应用程序,并使用Prism和委托命令将UI与视图模型分离

当用户从UI而不是从视图模型或服务对特定单元格进行更改时,我需要调用一些其他功能

我已经创建了附加的行为

public static class DataGridCellEditEndingBehaviour
{
    private static readonly DependencyProperty CellEditEndingProperty
        = DependencyProperty.RegisterAttached(
        "CellEditEnding",
        typeof(CellEditEnding),
        typeof(DataGridCellEditEndingBehaviour),
        null);

    public static readonly DependencyProperty CommandProperty
        = DependencyProperty.RegisterAttached(
        "Command",
        typeof(ICommand),
        typeof(DataGridCellEditEndingBehaviour),
        new PropertyMetadata(OnSetCommandCallback));

    public static readonly DependencyProperty CommandParameterProperty
        = DependencyProperty.RegisterAttached(
       "CommandParameter",
       typeof(object),
       typeof(DataGridCellEditEndingBehaviour),
       new PropertyMetadata(OnSetCommandParameterCallback));

    public static ICommand GetCommand(DataGrid control)
    {
        return control.GetValue(CommandProperty) as ICommand;
    }

    public static void SetCommand(DataGrid control, ICommand command)
    {
        control.SetValue(CommandProperty, command);
    }

    public static void SetCommandParameter(DataGrid control, object parameter)
    {
        control.SetValue(CommandParameterProperty, parameter);
    }

    public static object GetCommandParameter(DataGrid control)
    {
        return control.GetValue(CommandParameterProperty);
    }

    private static void OnSetCommandCallback
        (DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
    {
        DataGrid control = dependencyObject as DataGrid;
        if (control != null)
        {
            CellEditEnding behavior = GetOrCreateBehavior(control);
            behavior.Command = e.NewValue as ICommand;
        }
    }

    private static void OnSetCommandParameterCallback
        (DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
    {
        DataGrid control = dependencyObject as DataGrid;
        if (control != null)
        {
            CellEditEnding behavior = GetOrCreateBehavior(control);
            behavior.CommandParameter = e.NewValue;
        }
    }

    private static CellEditEnding GetOrCreateBehavior(DataGrid control)
    {
        CellEditEnding behavior =
            control.GetValue(CellEditEndingProperty) as CellEditEnding;
        if (behavior == null)
        {
            behavior = new CellEditEnding(control);
            control.SetValue(CellEditEndingProperty, behavior);
        }
        return behavior;
    }
}

public class CellEditEnding : CommandBehaviorBase<DataGrid>
{
    public CellEditEnding(DataGrid control)
        : base(control)
    {
        control.CellEditEnding += OnCellEditEnding;
    }

    private void OnCellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
    {
        ExecuteCommand();
    }
}
调用事件时,我在VM中的delegateCommand中没有任何eventargs,如何检索事件args,可以通过命令参数设置它吗?如果是,如何将事件参数传递给委托命令

在CellEditEndigEvent期间,该值尚未存储到VM中,因为它仍在转换中,是否有一种方法可以从处理程序强制执行该操作,因此我不需要从CellEditEndingEventArgs读取值,而是可以直接从VM读取值


这是附属财产。你用它就像 local:DataGridCellEditEndingBehavior.CommandParameter={针对要传递的任何对象进行绑定}


您可能已经实现了自定义DataGrid,它具有指示已编辑的单元格或类似内容的自定义属性

我在尝试解决类似问题时遇到了这个问题-在MVVM应用程序中,我们有一个带有DataGrid的UserControl,因此需要将RowEditEnding事件绑定到命令。我无法完全遵循上面的示例,也无法确定如何找到CommandBehaviorBase

部分基于上的答案,我实现了以下附加行为:

Public Class DataGridHelper
Public Shared ReadOnly RowEditEndingCommandProperty As DependencyProperty =
    DependencyProperty.RegisterAttached("RowEditEndingCommand",
                                        GetType(ICommand),
                                        GetType(DataGridHelper),
                                        New UIPropertyMetadata(AddressOf OnRowEditEnding))

Public Shared Sub SetRowEditEndingCommand(control As DataGrid, command As ICommand)
    control.SetValue(RowEditEndingCommandProperty, command)
End Sub

Private Shared Sub OnRowEditEnding(dependencyObject As DependencyObject, e As DependencyPropertyChangedEventArgs)
    Dim control As DataGrid = TryCast(dependencyObject, DataGrid)
    If control Is Nothing Then
        Throw New InvalidOperationException("This behavior can be attached to a DataGrid item only.")
    End If

    If e.NewValue IsNot Nothing AndAlso e.OldValue Is Nothing Then
        AddHandler control.RowEditEnding, AddressOf RowEditEnding
    ElseIf e.NewValue Is Nothing AndAlso e.OldValue IsNot Nothing Then
        RemoveHandler control.RowEditEnding, AddressOf RowEditEnding
    End If
End Sub

Private Shared Sub RowEditEnding(sender As Object, e As DataGridRowEditEndingEventArgs)
    Dim element As UIElement = DirectCast(sender, UIElement)
    Dim command As ICommand = DirectCast(element.GetValue(DataGridHelper.RowEditEndingCommandProperty), ICommand)
    'command.Execute(Nothing)
    command.Execute(e)
End Sub
End Class
到目前为止,这似乎是可行的,而且似乎比上述方法更简单。我们将DataGridRowEditEndingEventArgs传递回参数中的命令,因此它在ViewModel中可用。这可能也适用于CellEditEnding事件

Public Class DataGridHelper
Public Shared ReadOnly RowEditEndingCommandProperty As DependencyProperty =
    DependencyProperty.RegisterAttached("RowEditEndingCommand",
                                        GetType(ICommand),
                                        GetType(DataGridHelper),
                                        New UIPropertyMetadata(AddressOf OnRowEditEnding))

Public Shared Sub SetRowEditEndingCommand(control As DataGrid, command As ICommand)
    control.SetValue(RowEditEndingCommandProperty, command)
End Sub

Private Shared Sub OnRowEditEnding(dependencyObject As DependencyObject, e As DependencyPropertyChangedEventArgs)
    Dim control As DataGrid = TryCast(dependencyObject, DataGrid)
    If control Is Nothing Then
        Throw New InvalidOperationException("This behavior can be attached to a DataGrid item only.")
    End If

    If e.NewValue IsNot Nothing AndAlso e.OldValue Is Nothing Then
        AddHandler control.RowEditEnding, AddressOf RowEditEnding
    ElseIf e.NewValue Is Nothing AndAlso e.OldValue IsNot Nothing Then
        RemoveHandler control.RowEditEnding, AddressOf RowEditEnding
    End If
End Sub

Private Shared Sub RowEditEnding(sender As Object, e As DataGridRowEditEndingEventArgs)
    Dim element As UIElement = DirectCast(sender, UIElement)
    Dim command As ICommand = DirectCast(element.GetValue(DataGridHelper.RowEditEndingCommandProperty), ICommand)
    'command.Execute(Nothing)
    command.Execute(e)
End Sub
End Class