Catel application-wide commands only in focused control - c#

Is it possible to register an application command in Catel which would fire only when specific control has a focus?
For example, in the Catel.Examples.WPF.Commanding example,
(https://github.com/Catel/Catel.Examples/tree/master/src/NET/Catel.Examples.WPF.Commanding)
if I replace TextBlock with TextBox and add RibbonButtons with ApplicationCOmmands.Cut and ApplicationCommands.Paste, these Application commands work only on focused TextBox.
Is it possible to make Refresh command execute only on the DocumentView which has a focus?
Alternatively, is there an example or guidance on using RoutedUICommands with Catel and its ICommandManager?
Thanks,
Tom

This is possible if you register an empty app-wide command. Then you can add an action / subcommand whenever you initialize a view model and unregister when the vm is closed again. This way, the command will be invoked against all "open" instances (and only be executable if one or more subcommands are available).

Related

Difference between Command (ICommand) and Click event

When should I use the Command and when to use the Click event?
F.e. if I have a Button in my UWP app what should I use?
When should I use the Command and when to use the Click event?
Yours is a broad question and I would simply answer with: "It depends".
Because:
The Command implements the ICommand interface and this means more code to add to your application but usually this won't change. Instead, the event handler doesn't require any interface implementation.
For every command you want, you have to provide the code that will handle the click and the CanExecute logic, to say when the command can execute. This is not requested in a simple event handler (like MyButton_Click). This means that, using a Command, you will have more control over the elements of your UI (the button won't execute anything if CanExecute is false).
When you want to add a Command, you will bind it to your DataContext (the ViewModel, if you implement the MVVM pattern). Instead, when you add a simple event handler (like MyButton_Click), the code will be placed in your code-behind that is the logic behind your main window. This means that implementing a Command, according to me, you'll have everything you need to modify in just one place (the ViewModel) instead of logic scattered everywhere in your project.
Of course, you can use whatever you want and my points are there just to give you an insight about these different implementations and you have to consider which solution is suitable for you, considering also the requirements you have been given (like: "Don't use event handlers" or "The Command is too advanced, let's just use something simple", etc.) and/or other constraints in your project.

How to pass a specific action to a viewmodel to execute on a button press?

I am trying to setup this scenario.
The basic premise is this. I have a message window, with couple of text fields and button, controlled by a viewmodel and a model. Originally window is displayed with showdialog() with button invisible while some background checks are going on.
If a an error occurs i would like the text in the window to change accordingly and a button become visible. I would also like this button to execute a specific action, a delegate or a static somewhere.
I would like to be able to pass this action to the viewmodel to be executed. The reason is i want to be reuse this window for different screen and button actions may change.
Thank you.
1.Define a command in your ViewModel(as a property with INotifyPropertyChanged).
Bind your button to this command:
Command={Binding MyCommand}
where MyCommand=property of yours viewmodel.
In case you need to change command action, just set property MyCommand to the implementation of command you are currently in need of.

RoutedCommand call fails using KeyGesture when using WindowsFormHost control in WPF

I have an application using cefSharp and some KeyGestures to open some forms. We were initially using the WPF ChromiumWebBrowser, but required the use of touch scrolling, which is not supported. As a result, we changed the control to the WinForms ChromiumWebBrowser inside a WindowsFormHost.
After the switch, KeyGestures bound to our RoutedCommands no longer fire.
After reviewing here, here, and here, I have tried several different solutions, but to no avail.
As per the above, when the window is deactivated, then activated the KeyGestures are routed appropriately (as discussed regarding breakpoints 'causing' the commands to work).
I have tried using the CommandManager.InvalidateRequerySuggested method on a timer or being called on loaded, after transfering focus to the window, after transfering forcus to another WPF control and after focusing the WindowsFormsHosts.
My command declaration is as follows:
RoutedCommand ShowAdmin = new RoutedCommand();
ShowAdmin.InputGestures.Add(new KeyGesture(Key.F1, ModifierKeys.Shift | ModifierKeys.Alt | ModifierKeys.Control));
CommandBindings.Add(new CommandBinding(ShowAdmin, ShowAdminForm));
I essentially have two questions:
1) Why am I not receiving the command. Is it because the WinForms control doesn't 'bubble' the keypress events?
2) What can I do to capture the keygesture without resorting to opening another window, only to close it again
Thanks in advance for your questions, comments and answers!
If you implement IKeyboardHandler you should be handle custom key press combinations, that's probably your easiest and cleanest solution.
https://github.com/cefsharp/CefSharp/blob/master/CefSharp/IKeyboardHandler.cs

Command source disabling and enabling

I read all about WPF commanding and i understand the GoF Command Pattern, still thought, i have one question about the process: how does the command target (for example a text box) tell the command source ( a button for instance) that it has changed state (eg. some text inserted into the textbox) so that the source can disable or enable itself or what ever it wishes to do. to put it in another way, how does the command target let the ICommand implementing class (the cut command for example) to trigger it's CanExecuteChangedEvent so that class can in turn let the command source know about state changes.
There is a class called CommandManager taking care of execution logic. You can call CommandManager.InvalidateRequerySuggested method to let system check your CanExecute methods.

Childwindows in MVVM

I'm having a problem understanding something about MVVM. My application relies on dialogs for certain things. The question is, where should these childwindows originate from? According to MVVM, viewmodels should contain only businesslogic and have zero actual knowledge about UI. However, what other place should I call my childwindows from, considering they're UI elements?
Doesn't this create tight coupling between elements?
Since you tagged the question with Prism, I'll suggest the way I've done it in the past using Prism. Have the IEventAggregator injected into your ViewModel, and then when you want to pop open the dialog, publish a "ShowDialogEvent" or something like that. Then, have another Module called "DialogModule" or whatever, which upon initialization subscribes to that event, and shows the dialog. Furthermore, if you want to pass data back to the original ViewModel, have the ViewModel of the dialog publish a "DialogCloseEvent" or something like that with a payload of the data you need. You can then subscribe to that event back in your main ViewModel.
See Handling Dialogs in WPF with MVVM
In the past, I have accomplished this by using Unity to resolve a custom interface that has a Show() method and a completed event. Then in the ViewModel I would call IScreen screen = container.Resolve<IScreen>(Resources.EditorWindowKey); and then just call screen.Show();.
The big advantage of this is that I can then just simply change my Unity configuration to remove the view when I'm testing my VM's.
The primary route I've been using to do this is to create a command inside your View layer. That command object accepts a parameter that is the ViewModel object that you want to display. The command then finds the appropriate ChildWindow, creates it and displays it with the parameter set as the content or however you will set it up. This way you can just bind a button's command property to that command, and its commandparameter to the object you want to show in the popup and your ViewModel objects never have to care how it's being displayed.
Prompting for user input (like saving a dirty file or something) doesn't work in this scheme. But for simple popups where you manipulate some data and then move on, this works very well.
The ViewModel sample application of the WPF Application Framework (WAF) demonstrates how to show a Modal Dialog.
I would suggest to use a controller in this scenario, say DI'ed dialogController backed up with a dialog shell. The source viewmodel(ie from where the request to open a dialog is originating) will make a call to dialogController.ShowDialog(<<ViewNameToHostInRegion>>,<<RegionName>>).
In Order to transfer the data to and from the dialog and sourceview you can use MessageBus. So essentially when you invoke the ShowDialog() you populate the messagebus, and when the close command of target View(The view hosted in Dialog shell) invoked - say in "Select" button -- Let the target view add/update the messagebus. So that source view model can work with updated data.
It has got many advantages :
1) Your source view works with dialog controller as BlackBox. ie it doesnt aware of what exactly the Dialog view is doing.
2) The view is being hosted in Dialog Shell -- so you can reuse the dialog again and again
3) Unit testing of source view is limited to test the actual functionality of the current viewmodel, and not to test the dialog view\view model.
One heads-up which I came across with this one is, while creating the test cases you may need to write testable Dialog controller which do not show the actual dialog while running the testcases in bunch. So you will need to write a TestableDialogController in which ShowDialog does nothing (Apart from deriving from IDialogController and provide blank implementation of ShowDialog().
Following is the psudeo code :
LocalMessageBus.AddMessage(<MessageKey>,<MessageActualContentAsObject>);
dialogController.ShowDialog(<TargetViewName_SayEmployeeList>);
Employee selectedEmployee = LocalMessageBus.GetMessage(<MessageKey>) as Employee;
if (selectedEmployee != null)
{
//doSomework with selected employee
}

Categories

Resources