I have a window control that contains four user controls (screens) in a wizard style environment. (i.e. only one user control will be viewable at all times) The window control has a series of buttons that act as the primary navigation between all the user controls.
----------------------------------
| |
| SCREEN x of 4 |
| |
----------------------------------
| |
| Back Next Cancel |
----------------------------------
The wizard will build a profile of information as the user completes each screen. I have defined a Profile type that implements INotifyPropertyChanged that will contain the information the user provides. So far, so good.
My question is: When the first user control (Screen 1 of 4) modifies the Profile type, how do I alert the Window? I'm trying to use MVVM and not use code-behind.
I tried setting up an event on the first user control. The window would be the subscriber to that event, but that's not working.
Is there a better approach for a user control to alert the main window that something has happened?
MVVM uses Commands instead of Click handlers. So you should have an implementation of ICommand interface ready to use or you can get it from any MVVM oriented Framework
If you want to keep things simple, here is the link how to use commands
What MVVM framework are you using? Most of them have an implementation of the Mediator pattern to handle communication between view models.
I use Cinch V2 and here you can find an explanation of how it implements the pattern and also see some code showing how to use it.
If you are not using a specific MVVM framework take the ideas from the implementation above and apply to you code!
Related
I have windows form application which has several user controls - each one is displayed when the relevant option is selected from a listbox.
Some of the user controls need to have access to data stored in a different user control so User Control A needs to know a value of a textbox stored in User Control B. I have done my exposing some properties in the user control B. This all works fine when the application first loads and no values are changed.
The problem I am having is if the value of the textbox in user control B is changed it is not picked up by user control A.
Do I have to do something with NotifyPropertyChanged? Any suggestions please?
Two solutions here:
Create a series of public properties and handle passing values where the Form objects are newed up.
Create an event to communicate when things change and register an event handler in the target Form to accept the change. This is similar in theme to the INotifyPropertyChanged interface but that's only required/advised for formal databinding scenarios.
I prefer events for this kind of thing.
In my application I have several user controls in a window. These user controls need to communicate to each other. My approach is as below
user control A fire a command which is to be handled by user control B.
main window recieves the command and fire a command to B
user control B handles the command.
My problem is how the main window can fire a command which can be handled in the VIEW MODEL of user control B?
Update:
SOLVED: One gloabl static RelayCommand for communication from the MainWindow to B and one Global RoutedCommand for communication from A to Main Window. Thank you for the responses.
The question is not tagged mvvm (yet), but I am assuming it since you mention a ViewModel. So to begin with, let's agree that ViewModels handle commands, not controls. If a control want to respond to a command being executed, expose a suitable CommandExecuted event that the control (View) can attach a handler to.
There is however another unknown that I cannot blindly assume:
Do you take it for granted that user controls A and B exist at the same time? If yes, then a very simple and low-tech solution would be to maintain references to both ViewModels at some level (perhaps the ViewModel for the Window itself?) and "bubble" the command up to there, where the dispatch to ViewModel B will occur. If not (in which case control B might not exist), what is the desired behavior?
With the information you have given so far, I 'd suggest using the Event Aggregator/Mediator pattern implementation of your MVVM framework. For example, Prism has EventAggregator; MVVM Light has Messenger; etc.
I would think that you'd want to have a dependency property on B that the main window could bind to. Your DP on B would then take the request and call it's view model.
The main window should not know anything about the inner workings of a Control. It should only know about the exposed properties from the control.
I have a wpf main window as the application shell containing status bar and a tab control with two tab items.
I have also two User controls and their View Model objects using MVVM.
I placed each user control on a tab item in the application shell.
My question is, I want the user controls to update the status bar on the main shell. What is the best way to handle that?
Thanks
I have the same question.
I don't know exactly what is the best way to do it but this my guess:
To me, the application class (I mean an override of it) is not right place to put it because it is too central. The status is per Window (Dialog).
Then, you could place it in the model of the Window but it is another bad idea (my opinion) because you will have to modify you model for something very virtual (status).
Personnaly, but I could be really wrong, I decided to declare a method in the parent window directly. Any model, if many, of any of my component that are part of that window could (preferably at initalization time) try to find the method (reflexion) and assign a delegate to it. Whenever you want to update the status you verifiy your delegate is not null and call it if its not. The delegate could be something like: SetStatus(string status). It's not perfect but it seems to respect hi cohesion and low coupling...
Hope it helps.
Eric
BXF (Basic XAML Framework)
http://bxf.codeplex.com/
From the BXF Documentation Page:
In its simplest form, Bxf acts as a message or request router from
application code to a presenter handler.
The idea is that your application code, typically your viewmodel code,
needs to do a set of basic things:
Show views
List item
Show status information
I have a composite WPF application. I am planning to implement tool bar functionality. There are few toolbar items (basically print, save, hide, expand, undo) which will be common to all views in the main region. For this i have created default toolbar module which will add these items (print, save, hide, expand, undo) to the toolbar region. when user clicks any toolbar item, this need to be handled by all 20 views in the main region.
For each toolbar item, i have associated a prism delegatecommand object.
sample:
private ICommand _printCommand;
public ICommand PrintCommand
{
get
{
if (_printCommand == null)
{
_printCommand =
new DelegateCommand<object>(**Print**, **CanPrint**);
}
return _printCommand;
}
}
Xaml, bind toolbar item to this command.
In the main region, we display close to 20 views. All these views have to subscibe to this command. I am thinking of using event aggregator to publish an event, and all the views will subcribe to this event.
For ex:
when the user clicks print, print command executes Print method which will publish print event. This event will be subcribed by 20 views and do further processing.
Am I implementing the toolbar in the right way?
I had initially thought of using composite commands. But by going through documentation it may not fit my requirements.
Ex : Application supports 40 views
Main region -> 20 Views that are active , all the view models are derived from baseviewmodel.
toolbar -> save button -> databinding to compositesaveallcommand(activeaware monitor enabled)
baseviewmodel -> save command -> registers/ unregisters based on specific filter conditions to compositesaveallcommand
when user clicks save button ,compositesaveallcommand looks for all registered commands that are active, and checks for all registered viewmodel commands calls (canexecute method, and all registered commands need to return true) then invokes child commands ( execute method) .
But in my case if the user make modifications in a single view , remaining 19 views there are no modifications. But I would like to execute save for single view. Looks like composite command will not invoke registered comamnds unless it can execute all.
If application allows the user to executes multiple commands at the same time, we may want to allow the user to save all the items on different tabs using a single command represented by a ribbon button. In this case, the Save All command will invoke each of the Save commands implemented by the view model instance for each item.
In the Stock Trader RI, for example, the Submit and Cancel commands for each buy/sell order are registered with the SubmitAllOrders and CancelAllOrders composite commands, as shown in the following code example (see the OrdersController class).
commandProxy.SubmitAllOrdersCommand.RegisterCommand(
orderCompositeViewModel.SubmitCommand );
commandProxy.CancelAllOrdersCommand.RegisterCommand(
orderCompositeViewModel.CancelCommand );
The preceding commandProxy object provides instance access to the Submit and Cancel composite commands, which are defined statically. For more information, see the class file StockTraderRICommands.cs.
public class MyViewModel : NotificationObject
{
private readonly CompositeCommand saveAllCommand;
public ArticleViewModel(INewsFeedService newsFeedService,
IRegionManager regionManager,
IEventAggregator eventAggregator)
{
this.saveAllCommand = new CompositeCommand();
this.saveAllCommand.RegisterCommand(new SaveProductsCommand());
this.saveAllCommand.RegisterCommand(new SaveOrdersCommand());
}
public ICommand SaveAllCommand
{
get { return this.saveAllCommand; }
}
}
This is exactly what the CompositeCommand does. I believe there are no examples (the Commanding QuickStart or the RI do not show active aware activity anymore, they did in Prism v1), but if you use the active aware stuff, you get what you are asking for.
The only thing is that you need to make sure that each of the individual DelegateCommands get their IsActive property correctly updated when they should (i.e. when the view gets activated).
I don't really like the idea of using the EventAggregator too much for things like this. Especially if you decided to create a multi document editor interface, each of your editors is going to be responsible for a lot of filtering to get the events that are only appropriate for them.
It might be easy to use EventAggregator for this purpose, but I think it's probably not really the right fit. That said, it's not really wrong... in fact I believe a few of the Prism samples do exactly this, but I think it puts too much responsibility on the constituents for filtering, rather than leveraging framework features.
Your subject suggests you were thinking of using CompositeCommands for this. Is there any reason you aren't doing this instead of using the EventAggregator? If you had a standard place where ViewModels could register their Commands designed to handle each of these buttons with a composite command sitting behind each one, wouldn't that give you the functionality you wanted? In addition to being able to handle the button commands, each of the constituent views/viewmodels would be able to disable buttons when they were inappropriate, etc.
Take a close look at the CompositeCommand samples in the Prism documentation and see if they don't do what you want.
I want to create a parent window and host a couple of childWindows inside it, and show them according to user events:
in other words:
on parentWindow.load() event, i load the main Childwindow.. and according to the user's choices i unload/close , and then load a different childwindow.
-all of that happening "inside" the parent window" -
giving the user the feeling of a paging application instead of a "forms/window" application.
is that doable ? and r there any better practices to have create a similar effect ?
I am not sure what you are going for exactly, but it seems like one of two options will help you:
TabControl/HeaderedContentControl: your main window could contain a large HeaderedContentControl (such as TabControl) and each of your "child windows" can be individual tabs. With a little coding, the user will be able to close certain tabs, make new tabs, etc. Josh Smith's MVVM demo application is an excellent example of the right way to do this.
Page-based navigation: using NavigationWindow and and Pages you can create a browser-style application that could have various child windows, each displayed one at a time, and with support for navigation history, hyperlinking, etc.