WPF Frame accessing parent page controls - wpf

I have a WPF page that contains a Listbox and a frame. The frame has various pages loaded into it determined by the selection within the Listbox.
Each page within the frame has a variety of different input boxes and has a Save Cancel button. When the Save button is clicked I need the content to be saved to the database and the Listbox in the parent page to be refreshed to reflect the new data.
Saving the data is easy but how do I initiate a refresh on the contents of the Listbox in the parent page when calling it from the page that inside the frame?
I need to somehow be able to access the parent pages controls to do this.
Any ideas?

It is technically possible to reach up into the parent control and have your way with the controls it contains, but it makes for code that's very difficult to maintain because if you change the structure of the parent control, you break code in all of the contained pages. That would be considered a very tightly-coupled design and it's often fragile.
A somehwat cleaner design would be to have your page classes raise an event when the Save button is pressed. Then your parent frame can sink the event and refresh whatever it knows needs to be refreshed after a save operation. That's easier to maintain because your components are more loosely coupled, but it still puts a lot of database knowledge into your GUI components. Such a design might be appropriate for a relatively simple app on which you don't expect to do a lot of maintenance or future enhancements.
The design pattern I prefer (as do many developers) is to isolate the database handling and business logic inside one or more classes with a simple programmatic interface that can be tested easily. The GUI components are kept as simple and thin as possible, so they can be easily changed if necessary. This is often called a Model-View-Controller pattern but there are other names for it. In your example, the "controller" class that encapsulates your business logic would have properties and methods for reading and setting information, and a "Save" or "Commit" method that writes changes to a database. Once the save is complete it would raise a "Saved" or "Changed" event that notifies all controls ("views") displaying information that the information has changed and they would refresh themselves based on the new values of the properties of your controller class.

Related

WPF MVVM: Decouple view bindings and dynamically setting bindings

I'm writing a fairly large WPF application that is following the MVVM structure. I would like to run my UI in basically 2 modes. The first being the normal day-to-day operational mode. The second is one that I've been wondering about for a while now...I would like to be able to run it in a "configure" mode where the user will see the UI in more or less the same fashion as the normal mode, except that a popup window would appear when they hover over (or maybe click) a control. This popup would allow the user to change certain bindings related to that control. I don't want to expose every property (or every control).
For example:
There is a TextBlock that has a binding to a pressure signal, now that user wants to change this binding to a temperature signal. They could start the UI in config mode, navigate to the screen with the TextBlock, select it, and see the Text property in a popup which they can then change to the new temp signal. This is a simplified exampe, but basically what I'm looking to do.
Is this possible? Remember the UI would have to write to the the View (XAML). Any help is appreciated.
P.S.
This would be a very useful but rarely used feature. It would be ok to maybe have 2 projects which ustalize the same View but different ViewModels and Models...at least that's what I've been thinking might be needed. Even if the normal mode UI would have to be recompiled after using the configure mode UI.
Every popup window should have its own VM (or they could share if it turns out to be an overkill due to small number of properties per popup) and communicate with the main VM via the message bus.
Store your bindings as User Settings and when the message arrives from the popup window VM, carrying the new binding as a payload, main VM would get that payload and save the appropriate user setting by simply calling Settings.Default.Save();
Based on your description, no reason to make it more complicated than that IMO...

WPF - MVVM Screen Management

Imagine you have a complex data object. It was complex enough that to edit the various properties of the object, it would be best for the user to have multiple screens. It's essentially a shopping cart for configured items.
So one screen would allow you to add items.
Another would allow you add modifications to those items, predetermined changes that have a cost associated.
A third screen would allow you to configure global settings for your items.
As I'm sure you can guess, each screen is operating on the exact same cart, just altering different properties and relationships of the items inside.
So, we're going to try to write the application using MVVM, and while discussing the various screens (as well as navigation between them) we arrived at the following question:
How do people generally manage application state when using MVVM? The navigation bar that the users will use to change screens will exist outside of the screen, but when a user clicks it, what common ways have people been using to hide one and show another?
More generally, how are people handling global application state? The user can only operate on one cart at a time, there can only be one user logged in at a time, only one screen can be shown at a time. Would it be best to create a singleton that stored these important properties and the ViewModels could keep a copy of them and subscribe to changes via an event aggregator?
As you can tell, I barely even know where to start with this problem, so any advice at all is welcomed and appeciated.
I would use ViewModels to track the application state.
One ViewModel controls the entire application, and it handles what page the user is currently on. The application itself is bound to the main ViewModel, and the majority of the application screen space is a ContentControl that is bound to ViewModel.CurrentPage. DataTemplates are then used to determine which View to display for whatever page the user is currently on
In the past I've used a global singleton for some objects (such as current user) and the ViewModels use a reference to this if needed. So if I wanted to display the UserName on a page, I'd have a property in the ViewModel called UserName and it returns Global.Instance.CurrentUser.UserName
For your type of situation I would look into PRISM. PRISM is a collection of patterns for developing WPF applications in a loosely coupled MVVM manner.
Specifically, for your example of the multiple screens and managing application state, using a "Controller" to load the views for the various representations of your ViewModel (the cart) into separate "Regions" would probably be a good start. There looks to be a great article on MSDN about getting started with PRISM, including composing user interfaces (Regions).

MVVM: One ViewModel structure for all Views vs. separate ViewModel structure per View?

I'm new to MVVM and need a bit of help.
My application consists of a number of different windows which display controls allowing the user to edit the data in the Business layer.
At the moment, each time the user opens a new instance of one of these windows, a ViewModel structure - classes and collections mirroring the Business layer - is created from scratch and databound to the View on the window, and is also configured to access the appropriate parts of the Business layer.
This is quite sluggush at the moment, and I have a suspicion it is because the application has to wait until all the new ViewModels are created and configured every time a window is opened. I also notice the RAM gets munched up quite quickly too.
Would it be better to have a single ViewModel structure which is created when the application starts, and then all windows and controls refer to this single instance? What is the convention for MVVM?
One ViewModel per view is pretty standard. You don't want to share instances of ViewModels, since they are (usually) stateful.
I would look deeper into the sluggishness before concluding it's the creation of the ViewModel that's causing it. Profile the application with a tool, set some stopwatches, or debug the app and see what the bottleneck is.
do you need to recreate your viewmodels every time you access your views?
if not it seems you use view first approach, maybe you should then use a viewmodel locator?
you can also take a look at viewmodel first approach, maybe this fits more in your application.

Sharing state/changes across ViewModels

I have an App which has a Tasks tab and a Projects tab. I decided to make a separate ViewModel for each of the tabs, TasksViewModel and ProjectsViewModel.
The Tasks tab has a new task area with an associated project pulldown and the Projects tab (obviously) has a list of projects.
What I'd like is for the pulldown on the Tasks tab to share the same collection as the Projects tab list so that any time I add or remove a project on the Projects tab the list on the Tasks tab is up to date automatically. This worked well with a single ViewModel but it was beginning to become quite unruly.
Should I not have split into two ViewModels? Is there a common method of sharing data like this? Perhaps pass the same ObservableCollection<Project> into each of the ViewModels? Perhaps some type of notification back to the TasksViewModel along the lines of ICollectionChanged.
Appreciate any insight/input!
The easiest solution here is often to use some form of Messaging Service to pass information between the two ViewModels.
For example, the MVVM Light Toolkit provides an IMessenger interface for situations like this.
Using a good IoC or DI toolset can help in this situation, as well. That would let you inject the project collection dynamically into both of your ViewModels, allowing a shared collection to be used in both Views.
It seems to me that your concepts of "Tasks" and "Projects" are part of your model, not part of your view model.
Consider this conceptual exercise: Suppose your app was written so that two users could use your application on two separate machines against a shared database, and one user adds a Project:
Would it be a good or a bad thing if the Project immediately showed up in the dropdown on the Tasks tab of the other user's screen?
Would it be a good or a bad thing if the Project showed up in that dropdown after the first user hit "Save" or "Commit" or "Ok"?
If the answer to either of these questions is "a good thing", your data is really part of your model not your view model. And it should be handled as such.
Your view model should incorporate your actual model by reference, and it is a good thing to share the model objects between view models as much as possible. In fact, ideally most of your application has a single set of model objects. The exception might be a dialog box where you want to be able to make some changes but then hit "Cancel" and not save them. In that case, the "Ok" button would copy data from the model maintained by your dialog box into the main application model. In this case the model objects used by the dialog and by the main application are different instances of the same class.
Now let's consider the case where you answered "a bad thing" to both of these questions. This would be an application where you never save your "Projects" list back to the main database/document/whatever, but it is a transient list used only for temporary work. In that case it would really be a view model, and I would attach it to the application (or whatever scope was appropriate) and have the two tabs access it.

WPF design question (custom control or mvvm)

Here is the scenario:
I have a visual that displays some data
The data to the visual can come in one of two ways
Via user input through the keyboard or mouse
Via some backend source
Both these data inputs can be of one of two forms
Control data or
Raw data for simple display
Control data causes changes in the visual
Raw data is simply showed as is
In other words, the view is being served by two masters, viz user input and backend input.
An example would be a multi-user game that has visuals controlled by user input
but may also have the same visuals controlled by some backend input (say tcp/ip).
Another example would be a terminal emulator that gets user inputs but also gets data
from another source be it telnet or serial, etc.
I was thinking of writing a WPF custom control for the visual. In other words,
it is a black box that will interpret the inputs and display the results.
Getting user input into this custom control is easy since one can listen for the
appropriate events and handle them as needed. However, how can one listen for the
inputs from the backend? Exposing a dependency property that one binds to does not make
sense but exposing a method on the visual that is called with the data also does not make
sense.
Another choice is the MVVM architecture where the Model is the backend data source
and the View Model does all the work. It gets both the backend data (via the model)
and the user inputs (via appropriate command bindings or some such) and it makes
appropriate sense of these and binds to the View to display these changes.
The advantage of the custom control is that it can be consumed as a control that
takes care of itself so that the consumer has to do very little work to use it
but the problem is getting data to it from the backend. The MVVM method is advantageous because it encapsulates the handling logic, view, etc neatly. The problem is that
this pattern has to be repeated for every backend. Thus, making the visual very bare bones
and exposing all the processing logic outside the control. Basically I want
to make it very easy to consume so that someone can take it and use it without adding
too much external logic to do processing etc. All they provide is their backend data
source that feeds into the visual.
Sorry for this being a lengthy post but I am learning WPF and this is an interesting design
question for me. All ideas, comments, etc welcome.
Thanks for reading.
I would definitely use the MVVM pattern. You get a very nice separation of concerns in your code, and your viewmodel can also be tested outside of the user interface. You may also be able to edit you view in Blend. I don't think that hooking up the viewmodel to the backend is more complicated than hooking up a custom control. You may decide to use dependency injection or a service locator to connect things. By using all these design patterns you get a more decoupled and testable solution.
I'd love to know more about CustomControls but in the mean time I think the best option is to use a UserControl as a DataTemplate:
http://www.codeproject.com/Articles/28060/WPF-UserControl-DataTemplate

Resources