Laden...

Was ist der Unterschied zwischen RelayCommand und DelegateCommand?

Erstellt von sindibad vor 7 Jahren Letzter Beitrag vor 7 Jahren 7.867 Views
S
sindibad Themenstarter:in
110 Beiträge seit 2012
vor 7 Jahren
Was ist der Unterschied zwischen RelayCommand und DelegateCommand?

Hallo zusammen,
Ich beschäftige mich jetzt mehr und tiefer mit MVVM in WPF.
nach ein paar tutorials/videos und Internet recherche
habe ich eine RelayCommand Klasse implementiert


using System;
using System.Windows.Input;

namespace MprintControl
{
    public class RelayCommand : ICommand
    {
        #region Fields

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

        #endregion // Fields

        #region Constructors

        /// <summary>
        /// Creates a new command that can always execute.
        /// </summary>
        /// <param name="execute">The execution logic.</param>
        public RelayCommand(Action<object> 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<object> execute, Predicate<object> canExecute)
        {
            if (execute == null)
                throw new ArgumentNullException("execute");

            _execute = execute;
            _canExecute = canExecute;
        }

        #endregion // Constructors

        #region ICommand Members

        /// <summary>
        /// Can Execute method for command
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        public bool CanExecute(object parameter)
        {
            return _canExecute == null ? true : _canExecute(parameter);
        }

        /// <summary>
        /// eventhandler check if the command can executed 
        /// </summary>
        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        /// <summary>
        /// execute method for command
        /// </summary>
        /// <param name="parameter"></param>
        public void Execute(object parameter)
        {
            _execute(parameter);
        }

        #endregion // ICommand Members
    }
}

was ist der unterschied zwischen RelayCommand und DelegateCommand? ist das das gleiche, nur zwei unterschiedliche Begriffe.
ich habe gelesen, dass man auch fertige Template in VS oder Frameworks für MVVM benutzen kann. welche habt ihr schon benutzt und was empfiehlt ihr. alles selber implementieren/kopieren aus Internet oder was fertiges.

in xaml
beim Button ist es kein problem


<Button Grid.Row="4" Grid.Column="4" Content="Continue" Height="23" HorizontalAlignment="Left" Name="buttonManuellGo" VerticalAlignment="Top" Width="75" Command="{Binding ManualPrintCommand}" />

bei Textboxen enter keybord event


 <TextBox Grid.Row="1" Margin="0,0,10,0"  HorizontalAlignment="Left"  Text="{Binding Path=PrintingData.ManufacturingOrder, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Height="23" Name="tbMO" Width="120">
                    <TextBox.InputBindings>
                        <KeyBinding Key="Enter" Command="{Binding StartOrderCommand}" CommandParameter="{Binding Path=Text, RelativeSource={RelativeSource AncestorType={x:Type TextBox}}}" />
                    </TextBox.InputBindings>
                </TextBox>

aber beim TextBox PreviewTextInput, könnte ich kein Command benutzen, habe ich über event in code behind und dann funktion von ViewModel augerufen. gibt es hier eine Lösung mit Command?


<TextBox Grid.Row="4" Text="{Binding Path=PrintingData.Start, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" Height="26" HorizontalAlignment="Left" Name="textBoxStart" VerticalAlignment="Top" Width="45" TextChanged="textBoxStart_TextChanged" PreviewTextInput="textBoxStart_PreviewTextInput" />

in ViewModel


  public ICommand ManualPrintCommand
        {
            get
            {
                if (_ManualPrintCommand == null)
                {
                    _ManualPrintCommand = new RelayCommand(param => this.StartManuellPrint(), param => this.CanStartManuellPrint());
                    //_ManualPrintCommand = new RelayCommand(StartManuellPrint(), CanStartManuellPrint());
                }
                return _ManualPrintCommand;
            }
            //private set;
        }

was mich hier stört ist 'param =>' beim Konstruktur von RelayCommand. kann man dies vereinfachen. ich bin noch kein Fan von diese schreibweise

es alles alles aber bestimmt ist ein Verbesserungspotential da
vielen dank für eure Verbesserungen und Tips

1.040 Beiträge seit 2007
vor 7 Jahren
  1. PreviewTextInput ist ein Event, daher kannst du da kein Command nutzen.

  2. Die 'param =>'-Schreibweise ist nur eine Möglichkeit von vielen. Das RelayCommand möchte eine Action<object> bzw. ein Predicate<object> haben.
    Wenn deine Funktionen folgende Signatur haben:

private void StartManuellPrint(object param)
private bool CanStartManuellPrint(object param)

haben, kannst du es so angeben:

new RelayCommand(this.StartManuellPrint, this.CanStartManuellPrint);
D
985 Beiträge seit 2014
vor 7 Jahren

Man kann einen Event mit einem Command verknüpfen

MVVM - Commands, RelayCommands and EventToCommand

1.040 Beiträge seit 2007
vor 7 Jahren

Was es nicht alles gibt. 😉

S
sindibad Themenstarter:in
110 Beiträge seit 2012
vor 7 Jahren

@p!lle

PreviewKeyUp is auch ein Event aber trotzdem gibt es diese Lösung was ich schon geschrieben habe in meinem ersten post


  <TextBox Grid.Row="1" Margin="0,0,10,0"  HorizontalAlignment="Left"  Text="{Binding Path=PrintingData.ManufacturingOrder, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Height="23" Name="tbMO" Width="120">
                    <TextBox.InputBindings>
                        <KeyBinding Key="Enter" Command="{Binding StartOrderCommand}" CommandParameter="{Binding Path=Text, RelativeSource={RelativeSource AncestorType={x:Type TextBox}}}" />
                    </TextBox.InputBindings>
                </TextBox>

ich schaue mal och ich das gleiche tun kann für PreviewTextInput
es gibt auch eine andere Lösung, die nur mit .net 4.5 funktioniert

1.040 Beiträge seit 2007
vor 7 Jahren

Naja, das ist ein Workaround, ändert allerdings nichts an meiner Aussage.

An ein Event kann man per se kein Command hängen.
Auch das EventToCommand, was Sir Rufo gepostet hat, wird das Command nur mit Hilfe einer weiteren Klasse an das Event anmelden können (schaue mir das EventToCommand gleich mal an).

Du nutzt jetzt ein KeyBinding, was mit dem PreviewKeyUp nichts zu tun hat, auch wenn es so aussieht.

S
sindibad Themenstarter:in
110 Beiträge seit 2012
vor 7 Jahren

ok danke für die deine Antworten.

hast du irgendwelche Erfahrungen mit fertigen MVVM Templates in Vs oder Frameworks oder implementiert alles lieber selbst?

siehst du sonst keinen weiteren Verbesserungspotential in mein code?

M
177 Beiträge seit 2009
vor 7 Jahren

was ist der unterschied zwischen RelayCommand und DelegateCommand? ist das das gleiche, nur zwei unterschiedliche Begriffe.

Im Prinzip ja. Zumindest versteht man unter den Begrifflichkeiten das gleiche.

Der Vollständigkeit seien noch die Attached Commands erwähnt 😃

Diese erlauben das setzen der Commands auch in einem Style. Kann man natürlich auch über DelegateCommands in Kombination mit den SDK Behavior (Interactivity ) lösen, weshalb man die Attached Commands kaum noch vorfindet.

Ich kann dir PrismLibrary/Prism empfehlen. Dort hast du die DelegateCommands

Wenn du dann auch nocht System.Windows.Interactivity zu den Referenzen hinzufügst kannst du dann auch sowas machen:


<ListBox ...>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="SelectionChanged">
            <i:InvokeCommandAction Command="{Binding SelectedItemChangedCommand}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</ListBox>

Beispiel siehe z.B. hier.

Mehr zu Prism siehe auch Gute Open Source Projekte zum MVVM lernen

212 Beiträge seit 2008
vor 7 Jahren

Für Commands verwende ich nur noch die CommandMap:

Simplifying commands in MVVM and WPF

Finde ich sehr gut, da die ViewModels so sehr übersichtlich bleiben.

Gruß
Christoph