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
PreviewTextInput ist ein Event, daher kannst du da kein Command nutzen.
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);
Man kann einen Event mit einem Command verknüpfen
@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
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.
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?
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
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