I know how to invoke relay command without parameter using mvvm pattern, but how to do the same with command with parameter?
https://i.stack.imgur.com/o7r5i.jpg
https://i.stack.imgur.com/zNkYR.jpg
https://i.stack.imgur.com/lmw3w.jpg
https://i.stack.imgur.com/iJnF0.jpg
If I understand you correctly, your command requires you to pass the TextEditor object in as a parameter, and you'd like to know how to do this in XAML. Since your TextEditor is named XMLView you'd simply bind this to the command parameter;
<KeyBinding Command="{Binding ValidateXMLCommand}" CommandParameter="{Binding ElementName=XMLView}" Modifiers="Control" Key="V" />
Notice the addition of CommandParameter="{Binding ElementName=XMLView}", this will pass the AvalonEdit TextEditor control instance as a parameter of the command.
Read more; https://stackoverflow.com/a/32064646/8520655
If you instead mean to invoke the RelayCommand from a ViewModel (in normal C#), you'd do the following;
if (ValidateXMLCommand.CanExecute(XMLView))
ValidateXMLCommand.Execute(XMLView);
Also, please do not post images of code, but rather your code formatted using the code style.
The control (e.g. Button / MenuItem) that you're binding your relaycommand to will have a CommandParameter property in addition to the Command property.
See here for an example of usage.
To execute a command from code behind, just call its Invoke() method, with the required parameter.
Related
Is there a way to pass entered key as command parameter in InputBindings of Window? I tried achive this by code below, but it isn't working.
<KeyBinding x:Name="KeyBinding" Command="{Binding ChoosePackageSizeFromKeyboard}" CommandParameter="{Binding ElementName=KeyBinding, Path=Key}" />
I don't wanna create binding for every key I wanna use, cause depending of condition it will be beetween 1 and 5 keys. Any ideas how to pass it to command?
I don't think it's possible to use KeyBinding the way you want to. You have to provide a value for the Key property for it to work.
What you could do instead is handle the KeyUp (or similar) event on the Window. If you want to bind on a Command, you can take a look at this SO answer for more details on how to pass the EventArgs to the command.
It seems much neater to me to implement a command in a class that represents that command, and derives from ICommand. This way I can also export and import commands in an MEF composite application.
Is this possible, or feasible? Is there a known pattern for accomplishing this?
I'm not sure how well this answers your question, since I don't know much about MEF.
There is no need to have direct references to command instances on your class, but you do need some way of presenting a binding source that returns one to a view. You can build a menu by binding a MenuItem's ItemsSource to a property that returns a dynamically generated IEnumerable of commands, for example.
You could also use a value converter to get a command on-demand for some arbitrary identifier:
<Button Command="{Binding Path=CommandId, Converter={StaticResource CommandConverter}}" />
Or pass the identifier directly from XAML through Binding.Source:
<Button Command="{Binding Source=DesiredCommand, Converter={StaticResource CommandConverter}}" />
In this case the string "DesiredCommand" would be passed to the converter.
In my Application i have a MainWindow that import over MEFedMVVM the ViewModel:
xmlns:mefed="clr-namespace:MEFedMVVM.ViewModelLocator;assembly=MEFedMVVM.WPF"
mefed:ViewModelLocator.ViewModel="MainViewModel"
And now i have my ViewModel too that realize the ViewModel:
[ExportViewModel("MainViewModel")]
public class MainViewModel: ViewModelBase
In my ViewModel i have a ICommand property for closing the window. The event for closing can comes from anywhere. And with help from the Cinch Framework 2.0 i realize a Simplecommand with Execute methode.
Question
How can i Close the Window from my execute methode? Over the dependency injection i haven't a constructor i can't register an event or give the view as parameter to the viewmodel.
Edit
However, a possibility which I think is not nice:
Call this in the methode
Application.Current.MainWindow.Close()
You can achieve this by writing an ICommand that passes the Window instance in as a parameter.
A good example is available here: How can I assign the 'Close on Escape-key press' behavior to all WPF windows within a project?
In that post the ICommand is eventually bound to a KeyBinding (so that the Escape key can be used to close the window) but you would be able to bind the command to any button or invoke it from anywhere within the view. The important part is to use a RelativeSource on your command parameter binding to reference the Window that you want to close
Edit in response to comments
The command is a singleton, but there is no requirement for it to be - it is only a singleton because it is stateless and it makes the binding easier. It acquires a reference to the Window through binding, so for a UserControl you can just use:
<Button Command="{x:Static mynamespace:CloseWindowCommand.Instance}"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" Content="Close My Parent Window" />
To be able to call it from view model code is slightly more complicated and needs a different approach; a good example can be found here: http://gallery.expression.microsoft.com/WindowCloseBehavior
I'm struggling to understand what is going on with the ContextMenu. I know it is rendered as a separate window, with a separate visual tree, so we can't use relative binding to bind a command exposed as a property of the user control. e.g. the following does not work:
<MenuItem Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=TestCommand}" Header="Test" />
But, if you set the data context of the user control to a view model that exposes a command as a property, the following will work:
<MenuItem Command="{Binding TestCommand}" Header="Test" />
What I don't understand is, how is the ContextMenu inheriting the value of the DataContext if it is not part of the visual tree. I would expect both of these examples to behave the same (i.e. both work or both fail).
The second binding works because of so called "inheritance context". You can read about it here: http://blogs.msdn.com/b/nickkramer/archive/2006/08/18/705116.aspx. Basically this is a kind of special case where some properties inherit data context of the owner object. Thus, for example, the inheritance context always works on properties of type Freezable (another interesting article about Freezables: http://drwpf.com/blog/category/freezables/).
Actually the article says that the inheritance context doesn't work on ContextMenu, but in version 4 they added it, so it actually works now as you've shown it in your example.
I am trying to use the MVVM pattern to write a WPF application. I am using WPF data grid (from the toolkit) which lacks the autofiltering feature. So I want to implement it. I've added a context menu to the column header template, it has MenuItem called "Filter" which should actually call the filtering method.
So I've set a MenuItem's command to be the appropriate DelegateCommand which goes to the ViewModel. The problem is that I need to pass the information about the actual column that has been right-clicked! If I wasn't using MVVM, I would implement an event handler which would receive a "sender" argument (the MenuItem), then I would find its parent (the ContextMenu), then its parent would give me the column. But how can I achieve the same thing here? How can I pass the sender to my command? Can this be done using ComandParameter?
I really don't want to use additional complicated patterns to achieve such a simple task. After all, MVVM should simplify the development and not vice versa...
Can you pass the Column header value as a Command Parameter and use that to get the Column details at the ViewModel?
You could try some relative source magic, but it might be easier on you if you can have a different ViewModel that you bind to for each header, like HeaderViewModelItem. From there you'd just be firing a DelegateCommand in your HeaderViewModelItem, rather on your larger viewmodel.
I've used this model with pretty good success. Gets around a little bit of databinding dance.
If you want to pass something into the command parameter it is important to note that a context menu is on its own visual tree. Luckily it still inherits the DataContext from its parent, so something like
<MenuItem CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}, Path=DataContext}" />
should get you the GridViewColumnHeader, or at least something in the visual tree of it.