I'm pretty new to WPF so I've been struggling with some basic concepts.
My application consists out of a main window containing various tabs. The first tab is used to add files, activating the other tabs which operate on the given files. For simplicity, let's call the latter "DataTabs".
I'm not sure about how to correctly communicate between the tabs. Currently, the FileInputTab uses a designated ICommand to do the following: Read the data, create a view model for the DataTab, and raise a "ViewModelReadyEvent" using the FileInputTab's view.
This event then bubbles up to the MainWindow, which activates the DataTabs and passes the created ViewModel on to them.
Now, two things I'm struggling with.
Populating the view model
Is it a better approach to populate the view model for the DataTabs inside their corresponding views, rather than from the FileInputTab that actually has nothing to do with it? This way, I could correctly establish a reference between the two, but I would have to perform the population separatly for every DataTab. Any thoughts?
Communication between "sibling" views
It doesn't feel right to let the event bubble up all the way to the MainWindow to let it orchestrate all inter-view communcation. I looked into RoutingStrategies, but I can't find any way to directly communicate between "sibling" views. I would like to raise an event in the FileInputTab and directly act on it in the DataTabs, without any intermediate.
Any thoughts, comments or book recommendations by WPF experts would be appreciated. Thanks in advance.
Using MVVM you could introduce a ViewModel for every tab. Then you could write a Service for the communication between the ViewModels. It is quite easy if you use the Messenger Pattern. One ViewModel sends a message to the Service and the Service leads it forward to the other ViewModel. The Service would also do the work, so your ViewModel would not have any business logic.
MVVM Light helps you a lot with the MVVM pattern.
You can use IEventAggregator to communicate between ViewModels.
Related
I am creating a desktop application using WPF & Caliburn MVVM. In my "Views" directory, I have several files that follow this pattern:
ExampleView.xaml <= this is the actual UI design...
ExampleView.xaml.cs <= what goes here?
Then I also have a ViewModel for each view.
Can somebody explain what should go in the ExampleViewModel.cs and what should go in the ExampleView.xaml.cs? It looks like my ViewModels inherit from "Screen", where my ExampleView.xaml.cs inherits from "Window".
Thanks!
That is your "Codebehind" for the view. Many people use the codebehind to interact with their view. However, many people prefer a decoupled approach called MVVM that uses a viewmodel instead. The MVVM architecture is more unit-testing friendly and easier for code reuse.
So in summary, the ExampleView.xaml.cs is used to interact with your controls on the view.
Well, your views can be inherited from Window or UserControl or other WPF classes. In MVVM the view is the user interface and the view model is an abstraction of the view exposing public properties and commands. Instead of the controller of the MVC pattern, or the presenter of the MVP pattern, MVVM has a binder. In the view model, the binder mediates communication between the view and the data binder.
But your view can contains UI-logic that is not depend on data from ViewModel. This logic can be added to [Name]View.xaml.cs files as View's (and inner control's) event handlers, for example OnLoad, OnResize. It calls Code behind.
I just wrote a couple WPF apps using MVVMLight Nuget and all of my [views].aspx.cs only have the auto-generated code. I didn't need to put anything in the views code behind because it goes in my view model. I also converted some web apps and a couple windows 8 store apps to MVVM and almost completely eliminated all code from the views code behind.
The only time I have put something in the views code behind is maybe to instantiate a view model to go along with that view in very isolated situations.
There is much debate out there whether to have zero code to follow MVVM best or having some code in the code behind is okay. Personal preference and based on work load, complexity, timelines, etc.
I'm designing a C# / WPF application, and trying to adhere to MVVM (but I don't mind taking shortcuts, as I'm quite a beginner).
I have a ViewModel and several Models. In the View there is a TextBox that is meant to log messages about what is happening in the models. The text of the TextBox is already bound to a string property in my ViewModel, but how can I give my Models the ability to append text to that TextBox without breaking the MVVM concept too much?
I was thinking about using Trace and a Trace listener for my TextBox. Is there any other (simple) way?
Thanks
If you put functionality like networking in your model, it's not a model anymore. It will have to many responsibilities and will violate the Single Responsibility Principle (SRP).
Reduce your models to contain only logic tied with the model class itself. Move functionality like networking into service classes.
Update is result of user action in the same ViewModel
Call service classes from ViewModel (i.e. in commands representing user actions) and if the call is successful, get the updated value.
Update action happens in another ViewModel or somewhere else (timer/polling)
If the sync happens somewhere else, use EventAggregator. Your service can fire an event/message, your ViewModel will subscribe to it. When receiving this event, update your ViewModel and rise PropertyChanged.
I have a little app with a overview of some items (entries). The title of the entry at the list in the overview is a property of the entry.
When I click an entry a kind of tab should open where I can edit the entry. When I edit and save the entry, the overview tab should update the next time.
Here a mockup for better understanding.
App is based on MVVM pattern. Each View has a ViewModel as DataContext. Each ViewModel uses a Model and each Model has a Database.
The overview tab have it's own View, ViewModel and Model (pair). Also the tabs. Each tab for entries use the same pair (singleton instance). Only a few bindings are updated If a other tab is selected.
My question is how to communicate between the tabs.
I have two approaches
Mediator Pattern (Bootstrapper combines two ViewModels with a mediator)
Each Model uses the same Database (Models listen to Database, ViewModel listen to Model)
But I dont' feel well with these approaches.
Should I communicate between Models or between ViewModels? Or is this the wrong way?
UPDATE
I really appreciate all of your answers. In my opinion none of them are wrong or right. I think it's a matter of taste which solution is right for one is. I really like the EventAggregator pattern. Here is a nice video from Karl Shifflett about the implementation of the EventAggregator pattern in PRISM. But it also explains the pattern itself.
#Thomas In my opinion it is a bad solution to do this in one ViewModel. ViewModels have to be separated. MVVM based on Separation of Concerns.
Mediator is a step in a right direction but an Event Aggregator is much more flexible. You can find dozen of implementations. For example, Prism has a ready-to-use implementation.
Communication is between ViewModels. ViewModels register themselves for notifications in the Aggregator and raise notifications on the Aggregator.
You should communicate between ViewModels, if the functionality is related to formatting Model data for display. If your are communicating data from one Model to another, then communicate between Models.
Here is a concrete example: The Microsoft.Practices.Prism namespace, which you can access with NuGet right in Visual Studio, includes a class called CompositePresentationEvent<T>, along with an EventAggregator class which does the actual communicating.
Someplace common to your entire application (I chose App.xaml.vb, but it can be any publicly scoped code file, and it works as well for C# as for VB), you define events by inheriting from that class, and supplying the type T which corresponds to the data you're sending. For example, if you want to send a message that contains a simple string, then declare:
Public Class MyEvent: Inherits CompositePresentationEvent(Of String) : End Class
In your Application class, you define an event aggregator:
Public Shared ReadOnly AppEventAggregator As IEventAggregator = New EventAggregator()
Those two items together give you the means to trade events between any two objects in your application.
This gives your entire application access to an event called MyEvent. Wherever you want to send the MyEvent message, you call its shared Publish(String) method:
Application.AppEventAggregator.GetEvent(Of MyEvent).Publish("This is my event message")
Then, to receive the event, you implement a private read-only field in the class where the event should land, something like:
Private ReadOnly MyEventToken As SubscriptionToken =
Application.AppEventAggregator.GetEvent(Of MyEvent).Subscribe(Sub(eventMessage) DoSomethingWithTheString(EventMessage))
...where DoSomethingWithTheString(eventMessage As String) would be where you process your event.
There's (a lot) more to Prism, of course, but never a need to use more of it than you need, and, as others have pointed out, lots of other MVVM frameworks with similar approaches to solving the same problem.
For me, it's usually a bad sign when I have to program for communication between view models. Sometimes, you have to make communication between view and view model, but the need for connecting two view models seems to always result in combining two view models if possible.
With your mockup, I felt the same bad feeling. Why do you have to have separate view models for tabs in first place? In your case, views can be separate but I don't see any benefit from separating view models. Thus, combining the two view models into one is my recommendation.
Maybe this Post is interesting for you, it Describe a Pattern for a Communication on Type basis. It allows you to Communicate between everything you want, without dependences between them
I'm trying to learn MVVM and WPF and I'm using the MVVM Light Toolkit. Here's what I'm not fully understanding and maybe it's due to an incorrect architecture of my UI.
What I'm trying to accomplish is pretty simple actually. This is a utility application by the way. I want a window that serves as the 'controller' so-to-say that has a set of buttons. Each button should change the content of a frame. Example: one button loads a 'screen' ( or a 'view' if you will ) that allows the user to configure an 'Agency' which is a custom object. Another button loads a list of Users from the Agency that was in the first 'screen'. This 'Users' view needs to also be loaded in the same frame. In fact, as of right now, the window with all the buttons really is only responsible for loading the 'screens' in the frame. The meat of the application will be within all the separate 'screens'
What I am not understanding is 1) how to let each screen/view know about each other since one is dependent upon the other. It seems that in MVVM the ViewModel shouldn't know about anything. But in my case, I need to pass information around ( such as my Agency ).
If I can get some hints on what I need to look into, that would be great.
Thanks!
Some ideas that might connect some of the dots:
You'll most likely have one viewmodel per view ("screen").
Each viewmodel will contain all of the logic for its corresponding view
Viewmodels can and will know about the models (Agency, Users)
Viewmodels can communicate with each other via the Messenger in MVVM Light
Think of MVVM Light's Messenger as an "application-wide eventing system". When you send a message out from one view model, any other view model can be listening for that message/event and react to it as needed.
Does that help at all? Keep your thoughts coming and I'll keep commenting and I'm sure the community will as well :)
Few things:
each of your screens, should be separate view (eg. user control or new window - I suppose you've done that already)
every part of model (eg. Agency, User) you want to display in your application, should be wrapped with its dedicated view model
your views don't really need to know about each other; you can use commands or events on view models to get rid of those dependencies
view model only needs to know about one thing: model it's building on
it's good to think about view as really simple class, with one single responsibility of rendering content; no logic, no code behind (unless it's purely UI/display related) is something to follow
You can try to prepare your models first (if you haven't done that already), then make view models for them (thinking what properties of models you want to expose to views) and once that's ready, build your views basing on view models. Other way around is also viable option - pick whichever feels more natural to you.
One more thing: since you mentioned you can display several screens in one (I assume) main area, think about equipping your view models with something along the lines of bool IsCurrentlyActive property. This way, you can easily show/hide views with button clicks and still utilize binding mechanism.
They shouldn't know about each other. That is what the Messenger is for controllers and views subscribe to the events they are interested in. That way they don't need to know or care where they event originated.
Hmm Kendrick is faster. What he said.
Also it sounds like you kind of want an Outlook type interface, some navigation that loads other views. I had the same question a while ago. How to do Regions in WPF without Prism?
To better understand the MVVM pattern look at this article: WPF Apps With The Model-View-ViewModel Design Pattern
Also I advice you to look at Caliburn Micro framework.
I'm trying to create an silverlight application using the MVVM design pattern. It's a kind of bank application.
I've watched a lot of tutorials on MVVM but something makes me real confused.
I have about fiwe usercontrols representing my views "TransactionsView", "AccountView" etc and a bunch of models "UserProfile" - containing user password, username and a list of UserAccounts, "UserAccounts" - containing name, balance and a list of AccountTransactions, "AccountTransactions" - containing a name, and ammount.
Should i create one modelview which contains my userprofile or should i create a viewmodel for every view i have? I'm a doing right so far? Or have i got it completley wrong?
Thanks
In MVVM, ViewModels are usually 1-to-1 with Views. There isn't a parity between number of ViewModel and Models, though.
View: UI
ViewModel: Handles changes to view state, forwarding them to the model if/when appropriate. Sends notifications from the underlying program back to the user. It may also do initial UI validation.
Model: Actual "guts" of the application. Algorithms, data storage, system calls etc go here. I put program flow here. I've seen other people put it in the ViewModel. That part is up to you to figure out.
A View always needs a ViewModel, hence 1-to-1 (it could have sub-models, but I'll leave that up to you to decide on/deal with. I'd start off with 1-to-1).
A ViewModel usually needs Models to actually "do work", but how many classes/instances is up to each app/problem you're trying to solve.
From what you explain you are going in the right direction. What viewmodel you create is a bit up to you, MVVM is not set in stone - its just a method. What I found through trial and ERROR was that it was smart to understand it well before digging myself in too deep.
I read many articles that didn't explain MVVM in a way I could understand. Finally I found a couple of articles by Jeremiah Morrill that were straight to the point and easy to understand: Article 1 and article 2.
One ViewModel per view is recommended for MVVM.
There's no real hard and fast rules but essentially there's normally one ViewModel per View. You can get into a situation where you want to share a view model across multiple views but it's rare.
Imagine what you want to see on the screen and each state the screen / controls on the screen might be in, everything that is needed on that particular screen (view) should have a corresponding property in your ViewModel that you can bind the View to. So, this translate to a single ViewModel for a particular View. The ViewModel itself can be tied into one or more model(s) in the back. At least that's how I understand it.