Questions regarding WPF commands - c#

I have a few questions regarding WPF commands.
Where should I put confirmation dialogs? Should I show them right inside the command callback function? What if in some areas in the application I don't want a command to show a confirmation?
If I have a user control that shows items that can be deleted. Should the command be in the application's view model, and I use it for the item deletion, or should the user control itself also have a command that in turn calls the view model's function? (Note: the application view model is the only one having the information needed to do this operation)
How can I pass data within a command? I am using mostly DelegateCommand, and upon firing a command for a grid item, I'd like to pass the selected item, otherwise the application's main view model would have to find the grid and figure out its selection which will hardcode the command to the grid and not make it reusable.

A bit of this is opinion and style . . . Here's my approach:
Question 1:
I have a utility class that handles any confirmation, and I use the lightweight messaging in MVVM Light to handle communication between the view, the confirmation, and the viewmodel.
Edit: A bit more information on point 1
From within my Command, I will send a message along the lines of
"ConfirmDeletionMessage", which is then picked up by my dialog utility
class. The dialog utility class displays the appropriate message to
the user, and checks the results. Based on the results, it will
either broadcast a "DeletionConfirmedMessage" or
"DeletionCanceledMessage," which is then handled by the ViewModel to
either complete or cancel the delete.
There is some risk involved if you have multiple subscribers to this
message, as you won't know what order they're going to be handled,
but if you have strict management on message consumers, or ensure
that they are able to run in a random order, this approach works
pretty well, and it separates your View and Model code in a testable
fashion.
Question 2:
This is a tough one, and it is going to depend on your overall application. I'm personally a fan of putting it in the item's viewmodel. That way, you don't have to worry about your third question as much. Instead, the delete action simply works on the item you're dealing with. However, if you have to act on data outside of your list item (like removing it from the list), it makes more sense for the command to be on the parent viewmodel.
Question 3:
Use the CommandParameter property. You can bind this to whatever you want.
EDIT to Answer #2
Mark Green (who commented below) got me thinking. I originally adopted this approach for WP7, and it absolutely suited what I needed to do. However, there are other ways of handling this that should absolutely be considered. Another option is a "confirmation class" that can be used by your viewmodel. If you are using an IoC kernel, this becomes easy to do with constructor / property injection. Alternatively, if you have other methods of getting the class, do so, but do it in a way that you can mock out in testing. It might look something like this:
public class ExampleViewmodel : ViewModel
{
private IConfirmDialogManager _dialogManager;
public ExampleViewmodel(IConfirmDialogManager dialog)
{
_dialogManager = dialog;
}
// ... code happens ...
private void DeleteCommand()
{
bool result = _dialogManager.Confirm("Are you sure you want to delete?");
}
}
With an IConfirmDialogManager interface that looks like this:
public interface IConfirmDialogManager
{
bool Confirm(string message);
}
Which you would then implement appropriately.

Where should I put confirmation dialogs? Should I show them right inside the command callback function? What if in some areas in the application I don't want a command to show a confirmation?
Confirmation dialogs and show message dialogs are views.
Your VM should have a way of notifying your view that it wants to display something or ask something, then the view should decide how to display it (status bar, window, pop-up, voice message, ...)
If I have a user control that shows items that can be deleted. Should the command be in the application's view model, and I use it for the item deletion, or should the user control itself also have a command that in turn calls the view model's function? (Note: the application view model is the only one having the information needed to do this operation)
The items control should raise a delete command. The VM should handle the command and decide what to do (the VM should have the list of the selected items and the view should be binding to that list).
How can I pass data within a command? I am using mostly DelegateCommand, and upon firing a command for a grid item, I'd like to pass the selected item, otherwise the application's main view model would have to find the grid and figure out its selection which will hardcode the command to the grid and not make it reusable.
Commands can have parameters (e.g. RoutedUICommand). The command binding can specify a binding expression for the parameter. However, the correct approach is for the VM to be the source of the selection with a two way binding between the view's selection and the VM's.

simply use a dialogservice in your viewmodel
it depends but nevertheless the object/viewmodel where the command is located can easily reached with RelativeSource binding
CommandParameter is one way. in fact you use mvvm all information you need should be bind to your viewmodel. so if you have a command and you need the selecteditem from a listview, you can bind it to the viewmodel and dont need to set this as commandparameter

Related

Mvvm - How to capture in the ViewModel, the UI's data-bound Control's Name/Id, using a Parameter Command? Is there a clear cut way I'm missing?

Mvvm, Wpf, VS2015
Hi All! I have googled this till my fingers bleed! But just hacks and work-arounds, or partial use of code behind.
My Wpf-Mvvm app uses Speech Synthesis.
Each button, (and in the next iteration, buttons using the selectedItem Index of Lists or ComboBoxes, to select the content(text)to be synthesized) specifies different content to be synthesized.
Sticking with Mvvm principles, in my viewModel, I need to capture which button, based on the List or ComboBoxes' SelectedItem/Value that is bound to the Parameter Command.
Why? So I can have the app synthesize the content(text/words)the user selects to hear. If not, I have to make separate commands and speech synthesizer methods for each.
There must be a simple clear-cut way. What am I missing here?
I thought of updating the Model's properties to reflect user's selection and use User Settings to persist,but have not tried yet.
Otherwise the Model's properties are accessible so far as encapsulation-wise to the ViewModel, but the property values from the Model still are not visible in viewModel.
I need the command bound control's ID/Name to route the content to be synthesized based on the model's class properties. But when I instantiate the model from the viewModel,
the model's properties are not there. I presume instantiating the Model class object from the viewModel, is in a different memory location, than the Model.
So I will try using User Setting's persistence for these properties, if no one else has a better way.
There has to be a clear solution to this, I hope :)
I know the View and ViewModel are supposed to not need to know what the other is doing. In this case though, I clearly need the List or ComboBoxes' Id or Name and their SelectedItem index.
I also need the button's Id or Name, because I have several groupings of content to choose from, and several buttons starting the synthesizing method.
Example: If the text content of an announcement to be synthesized, held in separate XML(SSML) files with identifier key values of 941, 23, 508, etc.,
I need to know which the User Selected to hear.
I imagine simply capturing in the viewModel, the Data-bound List/ComboBoxes' Selected ID index would suffice.
Thank you so very much for your help.
-Flazz

MVVM without commands

I'm learning Silverlight/MVVM. Now I'm facing problem with Commands, that I think are just overcomplicated. I wanted to execute close on child window after command.
According to separation of concers it should be execute from view, as I understand.
As far as I looked for solution I found it and it wasn't trivial for such a trivial task.
To sum it up, I must say that separation of view, viewmodel and model are great ideas.
Also Binding from View to ViewModel is nice and clean.
But what about Commands. As I understand they are just piece of code to execute (like delegates).But they are too complicated and troublesome.
I want to know you opinion. What about idea that VieModel would have properties and normal public methods, that it will be executed from events of views. If I will not pass any view related element to the view model it still will be MVVM, right?
Of course, there will be one drawback, that i will have to bind separatly IsEnabled to properties in ViewModel to mimic CanUpdate functionality of Commands. It's not that you view doesn't know about ViewModel.
Views are not very testable, are they?
It would be very flexible. For example, in event for click i would do some strict view logic, call method from viewmodel object and then maybe call another method and after all that do some more view logic.
So, what do you think?
You can try using Cailburn.Micro. It is an open-source framework that runs over WPF and hides some of it complexities. For example, it replaces command-classes with just plain method calls.
You can implement windows-closing by returning a special result that will do the actual closing of the view. That way your ViewModel will still be fully unit-testable, as you can check that expected result is returned, and it will not be view-aware.
Here is an example on how to implement this: https://stackoverflow.com/a/10175228/258737

WPF: Changing the view from within the view

I want to achieve the following. I am designing a GUI with UserControls to allow the user to select and edit an action to be taken on items that the user can select elsewhere (in another part of the GUI).
Each action has a number of parameters that the user can edit (see figure). For each action I will need a different UserControl/View, since they have a different number of parameters/properties that can be edited.
As you can see in the figure, I want the user to use a drop-down menu to select and then edit an action. Therefore I need to somehow change the UserControl to that of the newly selected action from within the UserControl of the current action. How can I achieve this?!
Some time ago I needed similar thing. I solved it with special Singleton class using events.
This class would have event ChangeTriggered for example and then your other UserControl would subscribe to it.
Now you just need one method on Singleton to trigger this change. From now on it is just matter of custom EventArgs to transfer the data.
I am not sure how good design this is but it worked fine. Or you can check out Mediator design pattern.

MenuBarItems in MVVM

I am playing with mvvm and wpf. Now, my total solution is MVVM-friendly. The only thing i have put in code behind is the "make new product" & close buttons on the mainview.
Now im adding a menubar, and i was wondering if i can put these "make new product" & close Items in code behind, or is this a no go?
Thanks in advance.
The MVVM way to do it is commands. You can consider them as proxies between your declarative XAML and imperative VM.
Create CreateNewProductCommand, implementing ICommand.
Create a handler for the command performing the actual work as part of ICommand interface implementation (conventionally called On*** - OnCreateNewProductCommand) (you may want to pass paramteres for edit, which is supported by the interface too).
Expose your command as property of your VM.
Bind your menu item command (it'll likely have it, just search for properties containing Command) property to that command using standard binding syntax pointing to the relevant property created at a previous step.
This is not the only way to do it. There're more advanced techniques based on interactions/behaviors etc. Some of them would allow you to bypass command creation and bind your UI element event directly to the executable member of your VM.

Where to Create / Get / Cache the ViewModels?

First off, I'm new to MVVM, so please help me out on this :)
Suppose I have multiple views in my app. In my case, I have an editor view, and a browser view.
Both of them have to work with a viewmodel of a "node" I'm editing.
So where does the viewmodel actually get created ?
Suppose the Editor is told to edit a certain node - It could create a new "NodeViewModel" and work with that. But at the same time, there's a NodeBrowserView, which allows people to shortcut-select a different node.
Basicly - I need the EditorView to work with the same ViewModel as the BrowserView, so I need a generic "GetViewModelfor(X)" method.
So how is this supposed to work ? :)
Cheers :)
Both your editor view and browser view should operate on some kind of NodeViewModel. You shouldn't need separate view models just for the different view scenario.
Now, can you edit not-yet-shown-to-user node? If no (as in, user decides what is edited), view models should be created at the very first time their content needs to be presented to user. In most cases this would in some browser/details views, so that user can select element and then chose to edit it.
Edit:
Regarding your comment. NodeViewModel should be provided for editor view.
The providing part can be done for example via constructor injection or by setting view's data context manually. For example, when user browses all nodes in the browser view, he can double click on the list item and editor view will pop-up:
// this will probably be done in response to event
private void ListItemDoubleClick(object sender, EventArgs e)
{
NodeViewModel currentItem = // extract current list item
EditorView editorView = new EditorView(currentItem);
editorView.Show();
}
Alternatively, if you want to avoid this kind of strong coupling between CompositeView and EditorView you can always use events, however it's not always necessary.
One more thing I was thinking of in terms of design would be adding extra view model, call it NodesListViewModel. How the program flow might look like:
At application startup, get your nodes (be it from DB, file, service, anything)
Create instance of NodeListViewModel which takes dependency on IList<Node> (list of node entities)
NodeListViewModel will build and expose collection of NodeViewModel elements
Create instance of your main program window, which uses composite view. It needs NodeListViewModel as its data context.
Whenever user decides he needs to edit item, it's all ready. Browser has a list of all NodeViewModels, it can easily pick up current and pass it to dedicated view.
In cases like this I prefer to use a single main view model and have a "current item" that the view connects to instead. This is a lot easier to do instead of passing / creating new view models around each time a user clicks a different node / grid row / etc. I really see no need to a separate view model either when the same operations can be achieved in the overall view model. It reduces complexity and reduces the change of creating objects (view models) and leaving them hanging around because a reference to them was not released until the application is closed.

Categories

Resources