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...
Related
I have a C#.NET winforms project, and some controls are moving in design view whenever I build the project. Its only some of the controls (a panel with a label and datagridview in it, a button, a link button and a label) are all moving up on each build.
Has anyone seen this before or know how to fix it?
I think it is because of the AutoScaleDimensions. My guess is that your form was originally created on another machine.
Per MSDN.
"The AutoScaleDimensions property represents the DPI or font setting
of the screen that the control was scaled to or designed for.
Specifically, at design time this property will be set by the Windows
Forms designer to the value your monitor is currently using. Then,
when the form loads at run time, if the CurrentAutoScaleDimensions
property is different from the AutoScaleDimensions, the
PerformAutoScale method will be called to perform scaling of the
control and all of its children. Afterwards, AutoScaleDimensions will
be updated to reflect the new scaling size."
My guess is that for odd some reason when you build you project property (maybe some others) gets adjusted, but not on design time.
I think about few possible reasons:
You work on multiple monitors and/or there is some odd stuff with your adapter.
There is some problem with auto-generated designer file. Maybe it
edited manually somehow.
To fix I propose to do something I would do:
Recreate form from scratch if possible, by copy-pasting bits
one-by-one.
If not take some merging tool and insert fresh form
properties.
Also here is another interesting question on AutoScaleDimentions.
I am building a WPF application and using the MVVM for the first time. Overall using MVVM has been very interesting and one of the major benefits is the nice separation between the view and the model classes. It kind of disciplines (at least young developers) to not to mix them together.
We have a scenario where a window needs to be closed on a button click after a confirm message box. Now this can achieved the old-way by handling the button click event and closing the window in the Window class itself. Or we can do it MVVM way by creating a command in ViewModel, call Window to show message box..etc.
I understand what needs to done here, but my question is - is it necessary to use MVVM commands in all cases? Are there exceptions where we should not use commands e.g. simple UI actions? Are we not overusing MVVM here? What exactly will the benefits doing everything the MVVM-way?
Or we can do it MVVM way by creating a command in ViewModel, call Window to show message box..etc.
Let me pick this apart, mainly because IMVHO I see this done wrong all the time - a lot of people try to do too much in the VM. First of all, ask yourself the question:
Is the prompt related to the data or business rules in any way whatsoever?
If it isn't, i.e. it is simply a "are you really sure?" type prompt, then this SHOULD be done purely within the code behind of the view. The only time the viewmodel needs to have any knowledge or take any action is when it actually has something to do with the viewmodel, in which case you should expose a command from the VM, but the actual window closing is still done from the code behind of the view.
The VM should know nothing about the view that it is bound to, that is one of the purposes of the MVVM pattern. It can expose commands, but it shouldn't know that a user has interacted with a specific UI element1, and it shouldn't directly know that the window is about to be closed. It is okay for the VM to prompt (via a dialog service, which you do have, yeah?) that the current data is unsaved, but it doesn't know about the window in general because it doesn't know how its data is presented.
Sometimes you will walk a fine line, and it is easy to over analyze whether something should be done purely from the view, purely from the VM, or as a mixture of both. If you remember the role of the VM, and remember that it is okay to have code behind in the view (provided it is only doing view related stuff and handing VM stuff off to the VM) then 99% of the time you won't have a problem.
1 For example, the VM shouldn't know or care whether the user just clicked a button, hyperlink, or touched a hot spot in an image. The same command can be used to handle any of this.
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
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.
We have a scenario where we are exposing a set of WinForms UserControls via COM to a Legacy VB6 application. We have 3 different controls which have a MenuStrip on it that has the Control + F shortcut key mapped to a menu item which invokes a control specific find items dialog when the shortcut is entered. When we try testing this code in our WinForms shell the appropriate dialog (the one hosted in the active MdiChild) pops up when all 3 controls exist, but in the VB6 host the wrong dialog usually appears (it seems to always be the dialog for the first control which was created).
I'm fairly certain this has something to do with message pumps and all, but I can't seem to figure out how to ensure that the proper ToolStripMenuItem is getting invoked when we enter the shortcut key.
I know the option of using a global/singleton ShortcutKey manager/service that overrides ProcessCmdKey is a possibility, but that would be the last resort we want to fall back on. I just get a feeling that a message pump needs to be started.
This may be inappropriate to your needs. And it might only apply to VB6 specifically. But have you considered having VB6 use the standard menus, and just have it hold onto the keyboard shortcuts, and trigger things appropriately? You could then simply hide the individual menus (but they should still fire their events).