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

时间:2012-09-28 19:13:07

标签: wpf events mvvm datagrid

我正在研究WPF LOB应用程序和使用Prism和委托命令将UI与View Model分开。

当用户在特定单元格FROM UI(而不是View Model或Service)上进行更改时,我需要调用其他一些功能。

我创建了附加行为

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();
    }
}

我可以使用

调用相同的内容
local:DataGridCellEditEndingBehaviour.Command ="{Binding CellChangedCommand}"
  1. 当事件被调用时,我在VM中的delegateCommand中没有得到任何eventargs,我如何检索事件args,我可以通过命令参数设置吗?如果是这样,我如何将事件args传递给委托命令?

  2. 在CellEditEndigEvent期间,该值尚未存储到VM中,因为它仍在转换中,有没有办法可以强制它从处理程序发生,所以我不需要读取值从CellEditEndingEventArgs,我可以直接从VM读取?

2 个答案:

答案 0 :(得分:0)

这是附属财产。你喜欢它 local:DataGridCellEditEndingBehaviour.CommandParameter =“{绑定你要通过的任何内容}”

您可能实现了自定义DataGrid,它具有自定义属性,指示已编辑的Cell或沿线的某些内容。

答案 1 :(得分:0)

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

部分基于MvvmLight EventToCommand and WPFToolkit DataGrid double-click的答案,我按照以下方式实施了我们的AttachedBehaviour:

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传递回参数中的Command,因此它在ViewModel中可用。这可能也适用于CellEditEnding事件。