I have gone through few MVVM examples in SL/WPF and the very basic thing here is to implement ICommand interface. I have understood how MVVM works. However, I have a doubt regarding Execute method of ICommand interface.
The class which implements ICommand has Execute method as shown below.
public void Execute(object parameter) //Method to call when the command is invoked
{
// pointer to a method to be executed
}
In every example, I see that parameter in above method is NULL. Why? Can someone post a simple example of MVVM where this object parameter is put to use and not null ?
In the XAML you can set a CommandParameter
<Button Command="{Binding MyCommand}" CommandParameter="SomeData" />
Related
I am new to the MVVM pattern and I am trying to write my own custom Commands. What is the best method to write custom commands? (I read a lot of articles here and there, but could not obtain the idea of creating my commands). And in particular if someone can help me with the idea of creating a command, after a button is clicked to get the items from one ListView and put them in another. (The list view is bounded to ObservableCollection). Thanks in advance!
Just implement the ICommand interface. There are many on the web or even implemented in nuget packages. Search for RelayCommand or DelegateCommand with ICommand and you will find many implementations. After you have that you just wrap the VMs private method in a command. e.g.
ICommand startTestCommand;
public ICommand StartTestCommand { get { return startTestCommand ?? (startTestCommand = new RelayCommand(StartTest)); }
private void StartTest()
{
//This will execute if the Command is bound in XAML
}
To bind the command in XAML (assuming your view model is the data context) just bind the Command property of the button to "StartTestCommand" or whatever your command is called.
So in essence you do not "Create your own command" for what you are asking, but wrap the delegate for a Command mediator to handle preventing coupling. There are reasons to create your own commands, but I would recommend using what is out there.
You just have to implement the ICommand interface. Most MVVM frameworks have a generic delegate based command class which implements it (e.g. RelayCommand in MVVM light). You just pass the methods to execute to their constructor.
Currently i have the problem, that my business object overrides ToString for delivering data to some telerik control (RadListBox/RadListBoxItem). The model which overrides ToString implements INotifyPropertyChanged. Is it possible in c# to raise the method ToString to be changed? The initial values get's displayed well, but later changes will be ignored. For example:
public class ViewModel : UI.MVC.ViewModelBase
{
private string name;
[JsonProperty]
public string Name
{
get
{
return name;
}
set
{
name = value;
RaisePropertyChanged("Name");
}
}
public override string ToString()
{
return name ?? "--";
}
}
For example if Name is chagned, ToString should be called to get the new value.
EDIT
The ViewModel from above is embedded in another viewmodel. which is binded to a RadPropertyGrid:
public class FirstViewModel : : UI.MVC.ViewModelBase
{
public FirstViewModel()
{
SelectedItem = new ViewModel();
}
public object SelectedItem
{
get;
}
}
An instance of RistViewModel is the datacontext of the containing window.
XAML
<telerik:RadPropertyGrid NestedPropertiesVisibility="Visible"
x:Name="propertyGrid" Grid.Column="1" Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" IsGrouped="True"
Item="{Binding SelectedItem,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
Thank you very much!
Is it possible in c# to raise the method ToString to be changed?
No, it is not possible. You cannot force other code to call ToString() again as a direct consequence of some other event. For that matter, the only reason INotifyPropertyChanged works is that, by convention, code knows to subscribe to that event and call a property getter (which is a type of method) when the event is raised. The event doesn't actually force any code to call the property getter; it's just that anyone who bothered to subscribe to the event is almost certainly going to call that method when the event is raised.
Of course, you can always set up whatever mechanism between consenting pieces of code you want. But for code that itself has no reason to believe that it might get a different result from ToString() depending on when it's called, such a mechanism won't exist.
For example if Name is chagned, ToString should be called to get the new value.
You can always subscribe to INotifyPropertyChanged.PropertyChanged yourself, and then do something to force the ToString() method to be called again. It is not clear from the little code you provided how this might be done; maybe setting SelectedItem to null and then back to the desired object.
All that said, while I'm not familiar with the control you are using (RadPropertyGrid), assuming it follows the normal WPF model, then if it is in fact displaying the SelectedItem object in some way, I would guess that it's doing so in a manner that would be compatible with the use of a DataTemplate for that type. I.e. if you were to declare a DataTemplate for the ViewModel class, you could bind directly to the Name property. For example:
<DataTemplate DataType="l:ViewModel">
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
…and WPF would automatically update the displayed name if and when it changes.
Your ToString() method provides a default name value of "--". This could be incorporated into the Name property itself if you want, or you could add a new property, e.g. DisplayName that provides that (i.e. if for some reason you need Name to remain null when the property hasn't been set).
Without a good, minimal, complete code example that shows clearly what you're doing, it's impossible to know for sure what the best approach would be. But it would be surprising for a good WPF library to not support normal binding and templating mechanisms, and instead to rely completely on a ToString() override without any mechanism for value update notifications.
I am currently studying the MVVM pattern. So thus far I developed a simple demo programm which contains a view and a viewmodel with commands etc. Now I want to implement a Model but I am not quite sure how to do so. My demo contains a view with a textbox and a button. When the Button gets pressed a Command is launched.
The text from the textbox should be written in a textfile with upper cased letters. This functionality should be part of my model. How do i call this functionality from my viewmodel? Should the viemodel contain a instance of the model class and call a methode in the command execute? And how does the viewmodel get data from a model?
Thank you very much for your help!
Yes. You could instantiate a model object in the viewmodel and have it save the text in a textfile (Or whatever you want your application to do)
class ViewModelDefault : INotifyPropertyChanged
{
// Bound to your textbox
public string TextboxProperty { get; set;}
// Instantiate modellayer in viewmodel
private ModelClass _modelClass = new ModelClass();
// RelayCommand property -> bound to button on viewmodel
// Will execute method "ExecuteCommand" that contains a call to a method in the ModelClass
public ICommand ExecuteModelMethod
{
get {
RelayCommand relayCommand = new RelayCommand(ExecuteCommand);
return relayCommand;
}
}
// Method that the RelayCommand will execute.
private void ExecuteCommand()
{
_modelClass.SaveTextInTextfile(TextboxProperty);
}
...
}
In the code above I've made an example of how this could be done using RelayCommand.
RelayCommand is a class that makes use of delegates such as Action and Func. This means you can pass a method into the RelayCommand object and have it execute it.
What RelayCommand allows you to do is basicly binding a method through delegate to UI control in the view layer.
Read up on Delegates if you wish to study further on that topic.
Delegates (C# Programming Guide)
Usually for data storage and retrieval, I create a separate class called repository.
Your view model has an instance of the repository (or better: an interface of it).
In the repository class, you can do your file access.
By the way: If your view model just knows the interface of the repository, you could replace it later with a database access, and the view model would not be affected.
The view model can then interact with the repository i.e. call it methods when the command code in the view model executes.
You write...
"The text from the textbox should be written in a textfile with upper
cased letters. This functionality should be part of my model."
The model usually is just data, so a model class does not have functionality but only properties. Like I said: Do your data access in the view model or in the repository class.
In case of MVVM it would be good if the properties implement INotifyPropertyChanged , like the properties of your view model.
If you just want to write the content of a single text box, then your model would be a class with just one property.
I'm currently toying a little with MVVM pattern and trying commands. I find the default way (every Command class needs to implement from ICommand interface) quite boring, so I've created a new base class called, wait for it, CommandBase. It looks like this:
public abstract class CommandBase : ICommand
{
public virtual bool CanExecute(object parameter)
{
return true;
}
public virtual event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public virtual void Execute(object parameter)
{
}
}
Now every command just inherits from this base class and overrides what is necessary. I had a bug in the software, so I've put several breakpoints in my inheriting class and in this base class. Everything seems to work as expected, except one thing - the method CanExecute gets fired all the time. If I put the breakpoint inside the method, my application won't even start! If I delete this breakpoint, everything works again.
MainViewModel:
public class MainViewModel : ViewModelBase // base implements INotifyPropertyChanged
{
public ICommand NavigateCommand { get; private set; }
public MainViewModel()
{
NavigateCommand = new NavigateCommand(this);
}
}
My debugger gets to the constructor, instantiate the Command class and from now on the method CanExecute fires like crazy and I can't even open the application window, because the vs debugger won't let me. In my NavigateCommand I only override Execute method and set one property of the MainViewModel, nothing too fancy. CanExecute is left intact without overriding.
Just a note, the bug I've mentioned was just a typo of my View, it wasn't related to this issue. After I've fixed it, code works except this thingy.
Can someone provide an explanation why it behaves like this?
It's a 'normal' behavior, that CanExecute gets fired often by the CommandManager. You shouldn't try to debug into this methods. In case of unknow bugs, turn on the Common Language Runtime Exceptions at Debug -> Exceptions... Further information here.
Can I suggest that, unless absolutely necessary, you don't need to reinvent the wheel here. There are a number of excellent implementations of ICommand out there that you can use.
RelayCommand is probably the most commonly used, although DelegateCommand is also very well implemented, and is the standard ICommand implementation is the Prism framework.
How can I use the RelayCommand in wpf?
Relay command doesn't exist in WPF, it is just a external class that raised to prominence after it was defined in this MSDN article. You need to write it yourself if you want to use it.
Otherwise you can you the Delegate command from the WPF toolkit here which has a little bit of extra functionality over the RelayCommand code.
Ah, the question changed while I was typing this answer. Assuming that you are using the RelayCommand as defined above you need to supply it with one or two delegates, one that returns a bool which determines whether the command is in a valid state to be run, and a second which returns nothing and actually runs the command. If you don't supply a "CanRun" delegate then the command will consider that it is always in a valid state. The code used in the article:
RelayCommand _saveCommand;
public ICommand SaveCommand
{
get
{
if (_saveCommand == null)
{
_saveCommand = new RelayCommand(param => this.Save(),
param => this.CanSave );
}
return _saveCommand;
}
}
Declares a RelayCommand that will call the Save() method when triggered and return the CanSave property as a test for validity. When this command is bound to a button in WPF the IsEnabled property of the Button will match the CanSave property of the ViewModel and when the button is clicked (assuming it is enabled) the Save() method will be called on the ViewModel.
As an alternative to creating RelayCommand wrappers for all your methods can I suggest a free library and source that will allow you to use the binding {BindTo Save()}. I created it to simplify my bindings. It also makes relative binding much easier. You can find it here: http://www.simplygoodcode.com/2012/08/simpler-wpf-binding.html