I've already done a lot of winform and many WPF(MVC style).
I've looked into the MVVM pattern, and for now, the only thing I'm stuck on is Commands
.
The issue I got is that I don't find an adequate way to throw a command for many event.
I can't find how to invoke a command, that interaction on the Business context.
E.g. : I've the following MVVM model:
public class MyDemoViewModel : DependencyObject{
private IDataManager _manager;
private static readonly DependencyProperty _currentMessageDependancyProperty = DependencyProperty.Register("CurrentMessage", typeof(String), typeof(MyDemoViewModel), new PropertyMetadata(""));
public ICommand SendMessageCommand{get; private set;}
public String CurrentMessage {
get { return(String) GetValue(_currentMessageDependancyProperty); }
set { SetValue(_currentMessageDependancyProperty, value); }
}
public MyDemoViewModel(IDataManager manager){
_manager= manager;
SendMessageCommand = new SendMessageCommand(this);
}
public void SendMessage(String message){
_manager.SendMessage(message);
CurrentMessage = String.Empty;
}
}
With a simple command:
public class SendMessageCommand :ICommand{
private MyDemoViewModel _model;
public SendMessageCommand(MyDemoViewModel model) {
_model = model;
}
public event EventHandler CanExecuteChanged {
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter)
{
return !String.IsNullOrEmpty(_model.CurrentMessage);
}
public void Execute(object parameter)
{
_model.SendMessage( _model.CurrentMessage );
}
}
And a basic XAML:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Row="1" TextWrapping="Wrap" Text="{Binding CurrentMessage, UpdateSourceTrigger=PropertyChanged}"/>
<Button Content="Send" Grid.Column="1" Grid.Row="1" Command="{Binding SendMessageCommand}"/>
</Grid>
What should I do(I mean, in adequation with the MVVM pattern), to have my command executed when someone hit the Enter key in the TextBox? I mean, usually I would have set an event on "TextChanged" and send the command in the code behind. But I wan't to keep my code behind empty and without any knowledge of the model/business logic.
This is the most simple example that I've, but I can have the same kind of need for other operation(Operations that may not be accessible with a simple button).
Thank you
For your specific example, you can make use of InputBindings
. These allow you to execute some command in reaction to gestures (usually keyboard or mouse). Here is a quick example to achieve what you are after:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Row="1" TextWrapping="Wrap" Text="{Binding CurrentMessage, UpdateSourceTrigger=PropertyChanged}">
<TextBox.InputBindings>
<KeyBinding Command="{Binding SendMessageCommand}" Key="Return" />
<KeyBinding Command="{Binding SendMessageCommand}" Key="Enter" />
</TextBox.InputBindings>
</TextBox>
<Button Content="Send" Grid.Column="1" Grid.Row="1" Command="{Binding SendMessageCommand}"/>
</Grid>
For more advanced situations, such as reacting to various UI events, you can make use of Expression Blends Interactivity namespace (see here):
<TextBox>
<i:Interaction.Triggers>
<i:EventTrigger EventName="GotFocus">
<i:EventTrigger.Actions>
<i:InvokeCommandAction Command="{Binding SendMessageCommand}" />
</i:EventTrigger.Actions>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
An unofficial version of the Blend SDK can be found on NuGet here.