事件具有不兼容的签名 - EventHandler<T>

Event has an incompatible signature - EventHandler<T>

我创建了自己的 DataGrid,它实现了 RowClick 事件。 但是,在尝试将命令绑定到它时,它会抛出异常:

{"The event \"RowClick\" on type \"ExtendedDataGrid\" 具有不兼容的签名。确保事件是 public 并满足 EventHandler 委托。"}

因为我是 MVVM 的新手,所以我已经从最近几天收到的关于 MVVM 的所有输入中受到伤害。有人可以提示我(大部分)明显的错误吗?

提前致谢

这是我的(测试项目)代码:

public class ExtendedDataGrid : DataGrid
{
    public event EventHandler<DataGridRow> RowClick;

    public ExtendedDataGrid()
    {
        this.DefaultStyleKey = typeof(DataGrid);
    }

    protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
    {
        var row = (DataGridRow)element;

        row.PreviewKeyDown += RowOnKeyDown;
        row.MouseLeftButtonUp += RowOnMouseLeftButtonUp;

        base.PrepareContainerForItemOverride(element, item);
    }

    protected override void ClearContainerForItemOverride(DependencyObject element, object item)
    {
        var row = (DataGridRow)element;

        row.KeyUp -= RowOnKeyDown;
        row.MouseLeftButtonUp -= RowOnMouseLeftButtonUp;

        base.ClearContainerForItemOverride(element, item);
    }

    private void RowOnMouseLeftButtonUp(object sender, MouseButtonEventArgs mouseButtonEventArgs)
    {
        mouseButtonEventArgs.Handled = true;

        this.OnRowClick((DataGridRow)sender);
    }

    private void RowOnKeyDown(object sender, KeyEventArgs keyEventArgs)
    {
        if (keyEventArgs.Key != Key.Enter)
            return;

        keyEventArgs.Handled = true;

        this.OnRowClick((DataGridRow)sender);
    }

    protected virtual void OnRowClick(DataGridRow clickedRow)
    {
        if (null == this.RowClick)
            return;

        this.RowClick(this, clickedRow);
    }
}

Window.xaml

 <controls1:ExtendedDataGrid x:Name="extGrid">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="RowClick" SourceObject="{Binding ElementName=extGrid}">
                <i:InvokeCommandAction Command="{Binding MyCommand}" CommandParameter="{Binding SelectedItem,ElementName=extGrid}" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
        <controls1:ExtendedDataGrid.Items>
            <TextBlock Text="Text" />
        </controls1:ExtendedDataGrid.Items>
    </controls1:ExtendedDataGrid>

window.xaml.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;
        this._selectCommand = new DelegateCommand<DataGridRow>(x => 
        {

        });

//following works fine..
 this.extGrid.RowClick += (s, e) =>
        {

        };
    }

    private DelegateCommand<DataGridRow> _selectCommand;
    public ICommand MyCommand
    {
        get
        {
            return this._selectCommand;
        }
    }
}

DelegateCommand 实现:

public class DelegateCommand<T> : DelegateCommand
{
    public DelegateCommand(Action<T> executeHandler)
        : this(null, executeHandler)
    { }

    public DelegateCommand(Func<T, bool> canExecuteHandler, Action<T> executeHandler)
        : base(o => null == canExecuteHandler || canExecuteHandler((T)o), o => executeHandler((T)o))
    {
        if (null == executeHandler)
            throw new ArgumentNullException("executeHandler");
    }
}

/// <summary>
/// Stellt ein standard DelegateCommand dar.
/// </summary>
public class DelegateCommand : ICommand
{
    #region Events

    public event EventHandler CanExecuteChanged;

    #endregion

    #region Variablen

    private readonly Action<object> _executeHandler;
    private readonly Func<object, bool> _canExecuteHandler;
    private bool _isExecuting = false;

    #endregion

    #region Eigenschaften

    public bool IsSingleExecution { get; set; }

    #endregion

    #region Konstruktor

    public DelegateCommand(Action<object> executeHandler)
        : this(null, executeHandler)
    { }

    public DelegateCommand(Func<object, bool> canExecuteHandler, Action<object> executeHandler)
    {
        if (null == executeHandler)
            throw new ArgumentNullException("executeHandler");

        this._executeHandler = executeHandler;
        this._canExecuteHandler = canExecuteHandler;
    }

    #endregion

    #region Public Methoden


    public virtual bool CanExecute(object parameter)
    {
        return (!this.IsSingleExecution || (this.IsSingleExecution && !this._isExecuting)) && (null == this._canExecuteHandler || this._canExecuteHandler(parameter));
    }

    public virtual void Execute(object parameter)
    {
        if (this.CanExecute(parameter))
        {
            this._isExecuting = true;
            this.RaiseCanExecuteChanged();

            try
            {
                this._executeHandler(parameter);
            }
            finally
            {
                this._isExecuting = false;
                this.RaiseCanExecuteChanged();
            }
        }
    }

    public void RaiseCanExecuteChanged()
    {
        if (null != CanExecuteChanged)
            CanExecuteChanged(this, EventArgs.Empty);
    }

    #endregion

问题出在这一行:

<i:EventTrigger EventName="RowClick" SourceObject="{Binding ElementName=extGrid}">

EventTrigger class 期待使用 RoutedEventHandler 委托而不是 EventHandler 委托的路由事件。

这些是您必须在代码中进行的更改才能使其正常工作:

ExtendedDataGrid中:

public class ExtendedDataGrid : DataGrid
{
    public static readonly RoutedEvent RowClickEvent = EventManager.RegisterRoutedEvent("RowClick",
            RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(ExtendedDataGrid));

    public event RoutedEventHandler RowClick
    {
        add { AddHandler(RowClickEvent, value); }
        remove { RemoveHandler(RowClickEvent, value); }
    }

    public ExtendedDataGrid()
    {
        this.DefaultStyleKey = typeof(DataGrid);
    }

    protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
    {
        var row = (DataGridRow)element;

        row.PreviewKeyDown += RowOnKeyDown;
        row.MouseLeftButtonUp += RowOnMouseLeftButtonUp;

        base.PrepareContainerForItemOverride(element, item);
    }

    protected override void ClearContainerForItemOverride(DependencyObject element, object item)
    {
        var row = (DataGridRow)element;

        row.KeyUp -= RowOnKeyDown;
        row.MouseLeftButtonUp -= RowOnMouseLeftButtonUp;

        base.ClearContainerForItemOverride(element, item);
    }

    private void RowOnMouseLeftButtonUp(object sender, MouseButtonEventArgs mouseButtonEventArgs)
    {
        mouseButtonEventArgs.Handled = true;

        this.OnRowClick((DataGridRow)sender);
    }

    private void RowOnKeyDown(object sender, KeyEventArgs keyEventArgs)
    {
        if (keyEventArgs.Key != Key.Enter)
            return;

        keyEventArgs.Handled = true;

        this.OnRowClick((DataGridRow)sender);
    }

    protected virtual void OnRowClick(DataGridRow clickedRow)
    {
        var args = new RowClickRoutedEventArgs(clickedRow);
        args.RoutedEvent = RowClickEvent;
        RaiseEvent(args);
    }
}

这里我去掉了之前的RowClick事件,改了OnRowClick方法

添加一个名为 RowClickRoutedEventArgs 的新 class:

public class RowClickRoutedEventArgs : RoutedEventArgs
{
    public RowClickRoutedEventArgs(DataGridRow dataGridRow)
    {
        Row = dataGridRow;
    }

    public DataGridRow Row { get; set; }
}