I have a button in a Window that needs to call a function in pages contained within a frame. The page inside the frame will change based on a navigation contained in the main Window, so I will know the current Page within the frame.
Can someone help with how to call function in frame pages?
If you wish to approach this from an MVVM perspective, you'll want to make sure you're not working with the actual view here, but the ViewModel abstraction of it. In that case, your parent Window is probably backed by a ViewModel that contains some sort of a collection that backs your pages in the frame/tab control/container of choice. In that case, the button should link to a command on your Window-backing ViewModel and use the selected item in the collection to access the function. If you do not have a direct reference in this fashion (for example loading in from another module or something for frame contents) you can also use EventAggregator from the Prism/CAL libraries and publish an event when the window button is pressed and set up your pages to receive that event and handle the call there. EventAggregator can be a slick way to handle cross-module logic in a clean way.
Related
We have a main window that launches a child window. That child window dynamically loads custom usercontrols. In the contructor of these usercontrols, I pass a master object which, from this master object, a usercontrol specific viewmodel is generated and assigned as its datacontext.
All of this is working quite well. However, I jst discovered that when I close the child window at least some of my custom usercontrols are still active. How am I supposed to clean up my controls/viewmodels? Nothing seems to get called until the main window is closed. No destructor, no Dispatcher.ShutdownStarted, no dispose is available, no closing event, nothing I can find.
Anyone know what is supposed to be done to properly clean up after the window is closed?
I believe you need to think precisely about what is responsible for creating your views and your viewmodels, and what is responsible for determining whether or not something can close or not, etc.
It is usually a good idea for whatever that created something to destroy it. Therefore, if your child window is creating custom user controls it perhaps should be responsible for removing them. However, I believe if none of your objects has a reference (or strong event subscription) it should be eventually garbage collected. You could implement a finalizer/destructor and output a Debug.String to the output window to see when this might eventually happen. A good memory profiler could also be a good idea. However, it is also likely that you need more precise control of telling your ViewModel when it has been closed.
It's hard to say exactly what should happen in your scenario because it really depends on your exact and specific setup. Let me describe to you a scenario I had in my application. I had several views that were being displayed in tab pages. The tab pages had an X button to close the tab, and my View contained a hosted Windows Forms control that needed to have .Dispose() called to clean up resources as well as it needed to be informed of when to unsubscribe from composite commands in the file menu system. So, initially, I had a problem... how does my ViewModel unsubscribe from commands when the tab pages remove's the view? How does the View which is contained in a WPF control know when it has been removed? here's what I came up with
The tab page itself should not be telling my program if a view can or can not be closed
I needed the ability to cancel the closing event in case of program logic (File saved? Yes/no/cancel)
I needed the ability to detect when it was closed so I could cleanup/unregister at that exact moment
My solution was to implement an interface in my viewmodel called IRemovable which exposed a Removable boolean and a Remove() method which returns a boolean (was removed or not). My tab control only displayed the X button if Removable was true, Tab Control's Closing fired the Remove() of the IRemovable ViewModel and if it returned false it set the event args Canceled property to true if the ViewModel's Remove returned false.
Therefore, the remove of the view model could prompt the user for confirmation, unregister from commands, etc. The view could handle Closed event and call Dispose on any Windows Forms components etc. (of course I had to check if my View.DataContext is IRemovable).
Anyway, I know this isn't an exact answer but hopefully it helps you come up with some thoughts on how to solve your own problem
I have a view in Silverlight which contains a telerik:RadGridView with a number of columns.
I have it wired up so that when the user double-clicks on one of these columns, an event is fired. However, I don't know what to put in the event handler.
private void RowClicked()
{
//What goes here?
}
All I wish to do is load a popup view over my current view, with a close button so that the user can return to the previous view. A simple idea that is surely done a billion times everywhere, but I cannot figure it out or find examples of this anywhere.
Can anyone help?
Thanks very much.
You can set a previous view as input parameter to "RowClicked()" method. You will have a reference on previous view in current method. You can use it via Commands (bind a command and a command parameter to some action/event).
I have an one more idea (if you have a lot of views): you can create a navigation service. It is an interface, which contains events and methods. You should use events for navigation and methods - for sending needed data. Everyone of view should implement this interface. Needed event will be raised under view via some action (for example: button click). As for events: you can create a custom event handler, there you will set a sender instance and needed parameters. You should create a Navigation manager, there you should create a property for selected view and subscribe on everyone event. If user want navigate to another view, he will do some action and system will raise an event. You can create a custom container for created views. This container you can use for getting created instance of needed view. As you know, creating a new instance is heavy for system: need a some time and system resources. Will be easy to get a created instance of view instead a create a new. For setting default data or refreshing a binding you can user a custom method, contractor for which will be added to navigation interface.
It is a simple idea, which I used in one project. As for others samples: You can find another navigation frameworks and custom classes in internet. But, process of creating an own system will give you a level up in your work experience.
This seems to be a really naive question, but how on earth does one get the NavigationService from outside of a page, like say perhaps a view model? Everybody says that navigation should occur at the view, but I keep thinking, this is not a web page, its an application. The view model and business logic should control application flow, not the view. Is this in fact naive?
As far as I understand it, operations involving the View, i.e. UI, should be done by the View exclusively. When working with MVVM, the UI should not be controlled by the ViewModel or BusinessLogic directly (since they are not supposed to know anything about the concrete implementation of the View) but work with Messages.
That means, if we want to open an Editor window from the ViewModel we send a Message from the ViewModel that we want to open it and receive it in the View and open the window there. The same is valid for Navigating through different pages, where you would receive the Message in the MainPage (or whatever holds you pages that you want to navigate through) and handle everything there.
An alternative to that would be using a DialogService or something like that, which handles opening windows in a central place. However, since the NavigationService is a property of the Page class, we need to handle the message in the Page.
Example code, using the MVVM Light Toolkit: (not tested, partly taken from Shawn Wildermuth's RiaXBoxGames example):
ViewModel (e.g., put that in a Command for a Button):
Messenger.Default.Send<bool>(true, "GoToNextPage");
View (e.g. put that in a Constructor):
Messenger.Default.Register<bool>(this, "GoToNextPage", ignore =>
{
// your code to go to next page
});
another option is to create an event on ViewModel, fire this event when Command occurs and subscribe View to this event. Inside EventArgs you can carry which page to navigate to etc. I think simple and testable solution.
Robert
I just pass a reference to the Frame when I create the View-Model.
I have a shell with some buttons and tabs and a few modules in my application. Each module has a view with some elements like datagrids, stackpanels, text boxes, etc. They all have a name attribute. Now when I fire an event on a shell (like click a button) I would like to be able to something with those elements (like clearing all the information written by the user in provided textboxes). The problem is, shell does not see those elements and cannot recognize them. Is there a way to access them?
Thanks for any suggestions.
I'd suggest you take an approach like what the Stocktrader Reference Implementation does with CompositeCommands. Basically a CompositeCommand is an implementation of ICommand that contains a collection of other ICommands. In the RI, the CompositeCommands are exposed as static properties on a centrally available class.
In your case, you could have a composite ClearCommand. The viewmodel for the shell would expose this to the shell view so you could hook up, say, your Clear button to it.
The viewmodels for the various modules would then hook into this ClearCommand:
GlobalCommands.ClearCommand.RegisterCommand(new DelegateCommand(x => ClearAllFields()));
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