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

时间:2016-02-22 17:05:32

标签: wpf mvvm icommand

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

{&#34;事件\&#34; RowClick \&#34;在类型\&#34; ExtendedDataGrid \&#34;签名不兼容。确保事件是公开的并且满足EventHandler委托。&#34;}

由于我是MVVM的新手,我已经在过去几天所有关于MVVM的输入中受伤了。有人暗示我(大多数)显而易见的错误吗?

提前致谢

这是我的(testproject)代码:

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

1 个答案:

答案 0 :(得分:3)

问题来自这条线:

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

EventTrigger类期待路由事件,该事件使用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的新课程:

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

    public DataGridRow Row { get; set; }
}