2016-04-15 8 views
0

Wie DataGridTextColumn Änderungsereignis in WPF (MVVM) erstellen?

Wie DataGridTextColumn Änderungsereignis in WPF (MVVM) erstellen? Dank

+1

Könnte Bitte erläutern Sie, was Sie meinen. Möchten Sie einen Befehl von einem Ereignis in einer 'DataGridTextColumn' aufrufen? – Blinx

+0

Ich muss ein Ereignis erstellen und es in ViewModel aufrufen – Dinesh

+1

Meinen Sie "ein Ereignis erstellen" oder "rufen Sie eine Methode in dem Ansichtsmodell auf, wenn ein Ereignis ausgelöst wird"? Erstellen eines Ereignisses wäre sehr unterschiedlich – Blinx

Antwort

0

Sie einen Befehl an Datagrid CellEditEnding Ereignis binden können:

<DataGrid> 
    <i:Interaction.Triggers> 
     <i:EventTrigger EventName="CellEditEnding"> 
      <ec:EventToCommand PassEventArgsToCommand="True" 
           Command="{Binding ItemEditedCommand}" /> 
     </i:EventTrigger> 
    </i:Interaction.Triggers> 
</DataGrid> 

Und in Ihrem Code-Behind

private ICommand _ItemEditedCommand; 

public ICommand ItemEditedCommand => _ItemEditedCommand ?? (_ItemEditedCommand = new RelayCommand<DataGridCellEditEndingEventArgs>(ItemEditedCommand_Execute)); 

private void ItemEditedCommand_Execute(object param) 
{ 
    var cell = param as DataGridCellEditEndingEventArgs; 

    // Examine cell column and row and act accordingly 
} 

Sie müssen nicht unbedingt verwenden müssen EventToCommand Sie können ganz normal, was auch immer Sie verwenden Verwenden Sie innerhalb des Ereignisauslösers.

EDIT:

Hier ist eine Implementierung von RelayCommand und EventToCommand den Fall, dass Sie Probleme, sie zu finden ist:

EventToCommand:

using System; 
using System.Windows; 
using System.Windows.Input; 
using System.Windows.Interactivity; 

namespace MyProj.Helpers.Command 
{ 
    /// <summary> 
    /// This <see cref="T:System.Windows.Interactivity.TriggerAction`1" /> can be 
    /// used to bind any event on any FrameworkElement to an <see cref="ICommand" />. 
    /// Typically, this element is used in XAML to connect the attached element 
    /// to a command located in a ViewModel. This trigger can only be attached 
    /// to a FrameworkElement or a class deriving from FrameworkElement. 
    /// <para>To access the EventArgs of the fired event, use a RelayCommand&lt;EventArgs&gt; 
    /// and leave the CommandParameter and CommandParameterValue empty!</para> 
    /// </summary> 
    ////[ClassInfo(typeof(EventToCommand), 
    //// VersionString = "5.2.8", 
    //// DateString = "201504252130", 
    //// Description = "A Trigger used to bind any event to an ICommand.", 
    //// UrlContacts = "http://www.galasoft.ch/contact_en.html", 
    //// Email = "[email protected]")] 
    public class EventToCommand : TriggerAction<DependencyObject> 
    { 
     /// <summary> 
     /// Identifies the <see cref="CommandParameter" /> dependency property 
     /// </summary> 
     public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register(
      "CommandParameter", 
      typeof(object), 
      typeof(EventToCommand), 
      new PropertyMetadata(
       null, 
       (s, e) => 
       { 
        var sender = s as EventToCommand; 
        if (sender == null) 
        { 
         return; 
        } 

        if (sender.AssociatedObject == null) 
        { 
         return; 
        } 

        sender.EnableDisableElement(); 
       })); 

     /// <summary> 
     /// Identifies the <see cref="Command" /> dependency property 
     /// </summary> 
     public static readonly DependencyProperty CommandProperty = DependencyProperty.Register(
      "Command", 
      typeof(ICommand), 
      typeof(EventToCommand), 
      new PropertyMetadata(
       null, 
       (s, e) => OnCommandChanged(s as EventToCommand, e))); 

     /// <summary> 
     /// Identifies the <see cref="MustToggleIsEnabled" /> dependency property 
     /// </summary> 
     public static readonly DependencyProperty MustToggleIsEnabledProperty = DependencyProperty.Register(
      "MustToggleIsEnabled", 
      typeof(bool), 
      typeof(EventToCommand), 
      new PropertyMetadata(
       false, 
       (s, e) => 
       { 
        var sender = s as EventToCommand; 
        if (sender == null) 
        { 
         return; 
        } 

        if (sender.AssociatedObject == null) 
        { 
         return; 
        } 

        sender.EnableDisableElement(); 
       })); 

     private object _commandParameterValue; 

     private bool? _mustToggleValue; 

     /// <summary> 
     /// Gets or sets the ICommand that this trigger is bound to. This 
     /// is a DependencyProperty. 
     /// </summary> 
     public ICommand Command 
     { 
      get 
      { 
       return (ICommand)GetValue(CommandProperty); 
      } 

      set 
      { 
       SetValue(CommandProperty, value); 
      } 
     } 

     /// <summary> 
     /// Gets or sets an object that will be passed to the <see cref="Command" /> 
     /// attached to this trigger. This is a DependencyProperty. 
     /// </summary> 
     public object CommandParameter 
     { 
      get 
      { 
       return GetValue(CommandParameterProperty); 
      } 

      set 
      { 
       SetValue(CommandParameterProperty, value); 
      } 
     } 

     /// <summary> 
     /// Gets or sets an object that will be passed to the <see cref="Command" /> 
     /// attached to this trigger. This property is here for compatibility 
     /// with the Silverlight version. This is NOT a DependencyProperty. 
     /// For databinding, use the <see cref="CommandParameter" /> property. 
     /// </summary> 
     public object CommandParameterValue 
     { 
      get 
      { 
       return _commandParameterValue ?? CommandParameter; 
      } 

      set 
      { 
       _commandParameterValue = value; 
       EnableDisableElement(); 
      } 
     } 

     /// <summary> 
     /// Gets or sets a value indicating whether the attached element must be 
     /// disabled when the <see cref="Command" /> property's CanExecuteChanged 
     /// event fires. If this property is true, and the command's CanExecute 
     /// method returns false, the element will be disabled. If this property 
     /// is false, the element will not be disabled when the command's 
     /// CanExecute method changes. This is a DependencyProperty. 
     /// </summary> 
     public bool MustToggleIsEnabled 
     { 
      get 
      { 
       return (bool)GetValue(MustToggleIsEnabledProperty); 
      } 

      set 
      { 
       SetValue(MustToggleIsEnabledProperty, value); 
      } 
     } 

     /// <summary> 
     /// Gets or sets a value indicating whether the attached element must be 
     /// disabled when the <see cref="Command" /> property's CanExecuteChanged 
     /// event fires. If this property is true, and the command's CanExecute 
     /// method returns false, the element will be disabled. This property is here for 
     /// compatibility with the Silverlight version. This is NOT a DependencyProperty. 
     /// For databinding, use the <see cref="MustToggleIsEnabled" /> property. 
     /// </summary> 
     public bool MustToggleIsEnabledValue 
     { 
      get 
      { 
       return _mustToggleValue == null 
          ? MustToggleIsEnabled 
          : _mustToggleValue.Value; 
      } 

      set 
      { 
       _mustToggleValue = value; 
       EnableDisableElement(); 
      } 
     } 

     /// <summary> 
     /// Called when this trigger is attached to a FrameworkElement. 
     /// </summary> 
     protected override void OnAttached() 
     { 
      base.OnAttached(); 
      EnableDisableElement(); 
     } 

#if SILVERLIGHT 
     private Control GetAssociatedObject() 
     { 
      return AssociatedObject as Control; 
     } 
#else 
     /// <summary> 
     /// This method is here for compatibility 
     /// with the Silverlight version. 
     /// </summary> 
     /// <returns>The FrameworkElement to which this trigger 
     /// is attached.</returns> 
     private FrameworkElement GetAssociatedObject() 
     { 
      return AssociatedObject as FrameworkElement; 
     } 
#endif 

     /// <summary> 
     /// This method is here for compatibility 
     /// with the Silverlight 3 version. 
     /// </summary> 
     /// <returns>The command that must be executed when 
     /// this trigger is invoked.</returns> 
     private ICommand GetCommand() 
     { 
      return Command; 
     } 

     /// <summary> 
     /// Specifies whether the EventArgs of the event that triggered this 
     /// action should be passed to the bound RelayCommand. If this is true, 
     /// the command should accept arguments of the corresponding 
     /// type (for example RelayCommand&lt;MouseButtonEventArgs&gt;). 
     /// </summary> 
     public bool PassEventArgsToCommand 
     { 
      get; 
      set; 
     } 

     /// <summary> 
     /// Gets or sets a converter used to convert the EventArgs when using 
     /// <see cref="PassEventArgsToCommand"/>. If PassEventArgsToCommand is false, 
     /// this property is never used. 
     /// </summary> 
     public IEventArgsConverter EventArgsConverter 
     { 
      get; 
      set; 
     } 

     /// <summary> 
     /// The <see cref="EventArgsConverterParameter" /> dependency property's name. 
     /// </summary> 
     public const string EventArgsConverterParameterPropertyName = "EventArgsConverterParameter"; 

     /// <summary> 
     /// Gets or sets a parameters for the converter used to convert the EventArgs when using 
     /// <see cref="PassEventArgsToCommand"/>. If PassEventArgsToCommand is false, 
     /// this property is never used. This is a dependency property. 
     /// </summary> 
     public object EventArgsConverterParameter 
     { 
      get 
      { 
       return GetValue(EventArgsConverterParameterProperty); 
      } 
      set 
      { 
       SetValue(EventArgsConverterParameterProperty, value); 
      } 
     } 

     /// <summary> 
     /// Identifies the <see cref="EventArgsConverterParameter" /> dependency property. 
     /// </summary> 
     public static readonly DependencyProperty EventArgsConverterParameterProperty = DependencyProperty.Register(
      EventArgsConverterParameterPropertyName, 
      typeof(object), 
      typeof(EventToCommand), 
      new PropertyMetadata(null)); 

     /// <summary> 
     /// The <see cref="AlwaysInvokeCommand" /> dependency property's name. 
     /// </summary> 
     public const string AlwaysInvokeCommandPropertyName = "AlwaysInvokeCommand"; 

     /// <summary> 
     /// Gets or sets a value indicating if the command should be invoked even 
     /// if the attached control is disabled. This is a dependency property. 
     /// </summary> 
     public bool AlwaysInvokeCommand 
     { 
      get 
      { 
       return (bool)GetValue(AlwaysInvokeCommandProperty); 
      } 
      set 
      { 
       SetValue(AlwaysInvokeCommandProperty, value); 
      } 
     } 

     /// <summary> 
     /// Identifies the <see cref="AlwaysInvokeCommand" /> dependency property. 
     /// </summary> 
     public static readonly DependencyProperty AlwaysInvokeCommandProperty = DependencyProperty.Register(
      AlwaysInvokeCommandPropertyName, 
      typeof(bool), 
      typeof(EventToCommand), 
      new PropertyMetadata(false)); 


     /// <summary> 
     /// Provides a simple way to invoke this trigger programatically 
     /// without any EventArgs. 
     /// </summary> 
     public void Invoke() 
     { 
      Invoke(null); 
     } 

     /// <summary> 
     /// Executes the trigger. 
     /// <para>To access the EventArgs of the fired event, use a RelayCommand&lt;EventArgs&gt; 
     /// and leave the CommandParameter and CommandParameterValue empty!</para> 
     /// </summary> 
     /// <param name="parameter">The EventArgs of the fired event.</param> 
     protected override void Invoke(object parameter) 
     { 
      if (AssociatedElementIsDisabled() 
       && !AlwaysInvokeCommand) 
      { 
       return; 
      } 

      var command = GetCommand(); 
      var commandParameter = CommandParameterValue; 

      if (commandParameter == null 
       && PassEventArgsToCommand) 
      { 
       commandParameter = EventArgsConverter == null 
        ? parameter 
        : EventArgsConverter.Convert(parameter, EventArgsConverterParameter); 
      } 

      if (command != null 
       && command.CanExecute(commandParameter)) 
      { 
       command.Execute(commandParameter); 
      } 
     } 

     private static void OnCommandChanged(
      EventToCommand element, 
      DependencyPropertyChangedEventArgs e) 
     { 
      if (element == null) 
      { 
       return; 
      } 

      if (e.OldValue != null) 
      { 
       ((ICommand)e.OldValue).CanExecuteChanged -= element.OnCommandCanExecuteChanged; 
      } 

      var command = (ICommand)e.NewValue; 

      if (command != null) 
      { 
       command.CanExecuteChanged += element.OnCommandCanExecuteChanged; 
      } 

      element.EnableDisableElement(); 
     } 

     private bool AssociatedElementIsDisabled() 
     { 
      var element = GetAssociatedObject(); 

      return AssociatedObject == null 
       || (element != null 
        && !element.IsEnabled); 
     } 

     private void EnableDisableElement() 
     { 
      var element = GetAssociatedObject(); 

      if (element == null) 
      { 
       return; 
      } 

      var command = GetCommand(); 

      if (MustToggleIsEnabledValue 
       && command != null) 
      { 
       element.IsEnabled = command.CanExecute(CommandParameterValue); 
      } 
     } 

     private void OnCommandCanExecuteChanged(object sender, EventArgs e) 
     { 
      EnableDisableElement(); 
     } 
    } 

    /// <summary> 
    /// The definition of the converter used to convert an EventArgs 
    /// in the <see cref="EventToCommand"/> class, if the 
    /// <see cref="EventToCommand.PassEventArgsToCommand"/> property is true. 
    /// Set an instance of this class to the <see cref="EventToCommand.EventArgsConverter"/> 
    /// property of the EventToCommand instance. 
    /// </summary> 
    ////[ClassInfo(typeof(EventToCommand))] 
    public interface IEventArgsConverter 
    { 
     /// <summary> 
     /// The method used to convert the EventArgs instance. 
     /// </summary> 
     /// <param name="value">An instance of EventArgs passed by the 
     /// event that the EventToCommand instance is handling.</param> 
     /// <param name="parameter">An optional parameter used for the conversion. Use 
     /// the <see cref="EventToCommand.EventArgsConverterParameter"/> property 
     /// to set this value. This may be null.</param> 
     /// <returns>The converted value.</returns> 
     object Convert(object value, object parameter); 
    } 

} 

RelayCommand:

using System; 
using System.Diagnostics; 
using System.Windows.Input; 

namespace MyProj.Helpers.Command 
{ 
    public class RelayCommand : ICommand 
    { 

     #region Properties 

     private readonly Action<object> _execute; 
     private readonly Predicate<object> _canExecute; 

     #endregion 

     #region Constructors 

     public RelayCommand(Action<object> execute) 
      : this(execute, null) 
     { 
     } 

     public RelayCommand(Action<object> execute, Predicate<object> canExecute) 
     { 
      if (execute == null) throw new ArgumentNullException(nameof(execute)); 
      _execute = execute; 
      _canExecute = canExecute; 
     } 

     #endregion 

     #region ICommand Members 

     [DebuggerStepThrough] 
     public bool CanExecute(object parameter) => _canExecute == null || _canExecute(parameter); 

     public event EventHandler CanExecuteChanged 
     { 
      add { CommandManager.RequerySuggested += value; } 
      remove { CommandManager.RequerySuggested -= value; } 
     } 

     public void Execute(object parameter) 
     { 
      _execute(parameter); 
     } 

     #endregion // ICommand Members } 

    } 

    public class RelayCommand<T> : ICommand 
    { 
     #region Fields 

      readonly Action<T> _execute; 
      readonly Predicate<T> _canExecute; 

     #endregion 

     #region Constructors 

      /// <summary> 
      /// Initializes a new instance of <see cref="DelegateCommand{T}"/>. 
      /// </summary> 
      /// <param name="execute">Delegate to execute when Execute is called on the command. This can be null to just hook up a CanExecute delegate.</param> 
      /// <remarks><seealso cref="CanExecute"/> will always return true.</remarks> 
      public RelayCommand(Action<T> execute) 
       : this(execute, null) 
      { 
      } 

      /// <summary> 
      /// Creates a new command. 
      /// </summary> 
      /// <param name="execute">The execution logic.</param> 
      /// <param name="canExecute">The execution status logic.</param> 
      public RelayCommand(Action<T> execute, Predicate<T> canExecute) 
      { 
       if (execute == null) 
        throw new ArgumentNullException(nameof(execute)); 

       _execute = execute; 
       _canExecute = canExecute; 
      } 

     #endregion 

     #region ICommand Members 

      ///<summary> 
      ///Defines the method that determines whether the command can execute in its current state. 
      ///</summary> 
      ///<param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to null.</param> 
      ///<returns> 
      ///true if this command can be executed; otherwise, false. 
      ///</returns> 
      public bool CanExecute(object parameter) => _canExecute?.Invoke((T)parameter) ?? true; 

      ///<summary> 
      ///Occurs when changes occur that affect whether or not the command should execute. 
      ///</summary> 
      public event EventHandler CanExecuteChanged 
      { 
       add { CommandManager.RequerySuggested += value; } 
       remove { CommandManager.RequerySuggested -= value; } 
      } 

      ///<summary> 
      ///Defines the method to be called when the command is invoked. 
      ///</summary> 
      ///<param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to <see langword="null" />.</param> 
      public void Execute(object parameter) 
      { 
       _execute((T)parameter); 
      } 

     #endregion 
    } 
} 
+0
+0

Wenn Sie die EventToCommand-Methode wie ich gezeigt verwenden, wird ein DataGridCellEditEndingEventArgs als Ereignisargumente übergeben, die über Column- und Row-Eigenschaften verfügt, um zu überprüfen, ob es sich um die gewünschte Zelle handelt. –

+0

Ich habe meine Antwort mit einer vollständigen Implementierung der Teile aktualisiert, die benötigt werden, damit EventToCommand funktioniert –