2016-02-22 62 views
1

我創建了自己的DataGrid它實現了一個RowClick事件。 但是在嘗試將命令綁定到它,它會拋出該異常:事件有一個不兼容的簽名 - 事件處理<T>

{「上鍵入\‘「事件\」 RowClick \ ExtendedDataGrid \’有不兼容的簽名確認該事件是公衆和滿足EventHandler委託。「}

由於我是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 
+0

的事件必須是一個RoutedEvent,我打賭。 – Will

回答

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; } 
} 
+0

這是錯誤 - 謝謝! – user1021605