MVVM notification to UI - c#

NOTE: Please excuse my English. It ain't my native language - I sometimes misspell or use wrong time
SITUATION DESCRIPTION
First, I will describe the situation.
I'm working on a Windows Phone 8 App ( WP8.0 w/ .NET 4.5 in C#/XAML ). This is my first WP8 App and there is not much people around me who can help me with it, so I'm learning by myself from tutorials on the net and a few books (in other words, I'm rookie with not so much experience).
There is "not-so-large" amount of data I'm gathering from a webservices (which I will describe later) and I decided to use Model-View-ViewModel (MVVM) to store the data provided by it.
MVVM Structure:
this is just my pseudodiagram of how the MVVM structure looks like, description is below it
MainViewModel
--------------
|
+ several properties (Username, Password, etc...)
|
+ Commands (loadData1, loadData2, flush, ... - implementations of ICommand)
|
+ ------ PersonalInfoModel
| -----------------
| + several properties (name, surname, phonenumber, etc...)
|
|
+ ------ DataGroup1Model
| ---------------
| +several properties
| +ObservableCollection<Item1> (roughly 0 - 50 items)
| +ObservableCollection<Item2> (roughly 0 - 5 items)
| +ObservableCollection<string> (roughly 0 - 5 items)
|
| Item1 Item2
| ----- -----
| +several properties +several other properties
|
|
+ ------ DataGroup2Model (similar to previous)
...et cetera...
I have MainViewModel object containing few properties and few Commands (implementing ICommand) and also several Models, that contain other properties and observablecollections.
The MainViewModel is not populated by data at once, but over time as the user browses the application and requests it. Mainly because there are more webservices to gather it from - some of the data must be gathered based on user-specified criteria (like from which date to which etc.)
I decided to create one "persistent" (not sure if it's the right word) ViewModel that will be present throughout the entire application, because I sometimes need to combine data from several models in the page
For example I need to always display some basic userinfo in "userInfoBar" that is always present on the page + i need some information from DataGroup1Model and some from DataGroup2Model (which are populated by data from two webservices and are used in more combinations then just this one).
Webservices
I'm using webservices to gather data to populate the viewModel. Specifically one webservice with 9 methods, not sure about how to describe it - every one method gives me data about something, which i store in the datagroupModels (sometimes two datagroupmodels, like personalinfoModel and Datagroup1Model).
The webservices have been provided to me, i can't change them, i can only use them.
THE "PROBLEM"
I'm trying to figure out a good way to give signals to my pages that something is done. For example login sequence:
I have a page containing two TextBoxes which values are Binded to MainViewModel properties UserName and Password and a Button binded to Command Login in MainViewModel.
The login Command just fires up "doLogin" method, which uses the username and password properties and give it as credentials to instance of webserviceclient autogenerated by Visual Studio when adding the webservice and the client executes one of the webservice methods (asynchronous method) - for example login.
When this method is completed, it raises the Completed event associated with it and provides Result object in its CompletedArguments.
In the completed event i copy the data from the Result object to the viewModel.
At this point, it would be nice to give some signal to the UI that the login task is done and it should navigate to another page.
How should I do it?
Is there some preferred way to do it?
P.S.: If you have suggestions about something described here, I will be glad to hear them. Please also bear in mind that I'm a rookie, so i sometimes need explanation for dummies or get stuck at something basic and/or stupid.

Usually you notify the UI from the view model by just changing your data. For example, you could maintain some general “state” in a State property that is bound to in the UI. The UI could then display different things depending on which value that property has. You usually do that with data triggers. If it is less complicated, you can also just have a boolean that will tell you IsDataLoaded or something, i.e. if you loaded the data from the web service already. Or even simpler, if you want to display the result in the view, you would just have a property Result which you bind to. As long as you haven’t loaded the data, the value is null and the view would display the login form. If the data is not null (i.e. data was loaded) it will just show the data instead.
As for navigation, usually you would have own view models for every page of the navigation. So if you start with a login screen, you would have a “login view model”, and if the next page is a data visualization, you would have a “data view model”. Usually this is done using data templates. Data templates are templates that are dependant on a type. You would have a “meta” view model which basically just has a slot for the currently displayed view model. And then for each possible type, you would define a data template that defines its view for the specific view model type. And then to navigate, all you do is change the current view model in the meta view model.

If the notification needs to to the same view / viewmodel the implementation of INotifyPropertyChanged to get notifications should be sufficient.
So typically you would be updating a Success Property which in turn is also invoking the property changed event.
Alternatively if this login notification needs to travel across modules. To get the state to say a notification to a different modules (modules that are not know at the time of implementation). A publish subscribe model could be used.
https://msdn.microsoft.com/en-us/magazine/dn745866.aspx shows how to use MVVM Ligths publish mechanism.
Prisms EventAggregator could also be explored.

I would suggest you to take a look at prism http://compositewpf.codeplex.com/
This allow you to publish events or aggregate commands all over your app and to easily switch beetween views.
You'll have to read quite a lot documentation but this is worthwhile, I couldn't imagine develop a strong mvvm app without it now

Related

In MVC-4 (C# ) Is it best to use one large object that can be used many places, or several small objects that align with the views

I am new to asp.net MVC. I am adding to a project that has already been developed. There is currently a large user object (Fname, Lname, email_addr1, email_addr2, phone1, phone2, title, company, division...) It has around 18 fields.
I need to create two new pages that each use different fields of the current user object. As it has already been created, do I use the original object, and just use the fields I need?
Or do I create two new user objects, that have exactly the user fields needed for that view so that I can use them as view models?
If your Two Pages are separate in a way that each time you would navigate from page a to page b, the server has to handle a request then it would be smarter to shrink down the object in case the size of it impacts response time. Otherwise, if your Two Pages are not SSR (Rendered at Server Side), it would still be wiser to split the object into two smaller objects if and only if you fetch them via Ajax calls.
In any other cases, it will not result in any significant difference.
Its common to use 1 viewmodel for each view.
You'll maintain flexibility and independence.
Normally your view will change over time. If you tie them together, changing one will impact the other. In most circumstances this makes things harder, while making a copy of the fields initially is very easy.

Monotouch: send data back down the stack to another ViewController

I have a question concerning Monotouch.
The situation: I have 2 ViewControllers. The first (let's call it VC-A) looks similar to the contacts edit screen, meaning it has a TableView with multiple Sections each containing Buttons and TextFields. Now when the user clicks one of these Buttons, he will get to the second ViewController (VC-B), which displays a TableView containing data from the database. When the user clicks on any of these rows, VC-B will be closed and i want to display the selected database entry (string) as the title of the Button (in VC-A) which opened VC-B in the first place.
When I did an objective-C project last year, I managed to send data back down the stack by using delegates, but I haven't found a way yet how this works in Monotouch.
I have read several questions here on SO about using the AppDelegate or using singletons, but I'm not sure that this is the right way of returning data from a subview.
You can kind of copy the delegate pattern. Add a C# delegate to your VC-B that takes one parameter, some data structure.
In VC-B's "ViewWillDisappear", call the delegate it it is not null and pass the data on to it.
This way, your calling VC can get acces to the data but you don't need tight coupling between the two controllers. All it has to do, is register a delegate-method in VC-B.
As MonoTouch is .NET4 you can use Func<MyDataStructure> or Action<MyDataStructure> and don't need to use full qualified delegate types.
I have a static singleton class that I use to store "state" type data about my app - current settings and selections that are needed in many different places in the app. That's one way to approach this.
You could also pass VC-B a reference to VC-A when you create VC-B, so that it can explicitly access it's parent view and pass back values that way.
I actually prefer to use TinyMessenger for cross container calls I find this to be very very useful when you don't want to keep references to your heavy viewcontrollers around which could potentially result in memory leaks!
var messageHub = new TinyMessengerHub();
// Publishing a message is as simple as calling the "Publish" method.
messageHub.Publish(new MyMessage());
// We can also publish asyncronously if necessary
messageHub.PublishAsync(new MyMessage());
// And we can get a callback when publishing is completed
messageHub.PublishAsync(new MyMessage(), MyCallback);
// MyCallback is executed on completion
https://github.com/grumpydev/TinyMessenger

3 layer architechture and little details like dropdown lists

So I am refactoring a little application as an example to get more practice. The purpose of the application (let's say) is to collect the data from a "sign up new user" form, save it in the database. The only limitation I have is I have to use a special custom Data Access class which communicates directly with the database and returns the data (if applicable) in a DataTable object.
I have a question regarding a little details on a form and how do they fit in into the layer architecture. For example, my form has a drop down list that's fed from the database, but at the same time drop down list doesn't represent an object per SE (unlike a User that is a object, there is a class User that has multiple methods, data members etc). I don't want to have calls to the stored procedure right there in the code behind but I also do not wish to overdo on abstraction.
What would be an elegant way to take care of these little details w/o creating a class abstraction galore.
Hope I am being clear
Funny you should ask that. I went through that issue here.
These other Stack Overflow Questions that I've answered that show other parts (tangentially related):
Getting ListView Data Items from Objects
Working with ListViews
Concatenating Properties in a DropDownList
An option for getting non-object data to the UI is to create one or more lookup classes that are a bucket or "service" for getting odd bits of data for things like drop down lists etc...
Example:
myDDL.DataSource = Lookup.GetAllCountries(); // GetAllCountries is a static method
// set name/value fields etc...
myDDL.DataBind();
Using this methodology, you can still support tier separation. It's not object oriented or elegant, but it is very practical.
I don't know what's best practice, but what I do is I have a utility class that has a method that takes as arguments a DropDownList object and an enum, so I do
FillDropDown( ddlistPhoneType, DropDownTypes.PhoneTypes );
The utility class fills the dropdowns sometimes from the database, other times from XML, and occasionally some hardcoded values. But at least the GUI doesn't have to worry about that.

ASP.NET MVC C#: Bringing in data from multiple tables/queries into a view

Ok, I'm still getting the hang of asp.net and the MVC framework and converting my knowledge over from classic ASP and VB - so please be gentle.
I've got my first view (/home/details/X) functioning well thanks to previous help pointing me in the right direction, now I need to add data from multiple tables and queries/views to the MVC view (I hate that SQL and MVC both use the word view for different meanings).
I'm not looking for someone to write the answer for me (unless they're feeling really energetic), more so for someone to point me in the right direction of what I should be looking at and reading up on to understand it and do this myself.
My problem
There are multiple datasets which I need to display in this view, and each different data set has a proper PK/FK 1-M relationship established, and the resultant records would need to be looped through.
How I would have done this previously
In my classic ASP days, I would have just defined the SQL query at the head of the page where the data was to be used, with a select statement along the lines of:
SELECT * FROM query_name
WHERE query_uniquecolumnname = Request.QueryString("value")
Once that was done, you'd set the do while query_name NOT BOF/EOF up, then drop in the field names you wanted from that query and it was all done.
How do I acheive this now?
So, fast forwarding from my classic ASP knowledge, how do I acheive the same outcome with MVC?
The tables/views I wish to use are already defined within my data model (and the relationships are showing up in there which I would assume is a plus), I just need to work out how I could call these within the page and use the ID of the record being displayed in the Details view to ensure only related data is displayed.
Thanks in advance
The concept you are looking for is called a ViewModel. Essentially this is a custom class that you write that contains all the data that would be used in your view. So it is responsible for amalgamating all the data from the different tables and exposing it as properties. If you're using a data access layer, this is often as simple as bringing a few entities together. If you're using raw SQL to do it, then you would execute your queries when the properties were accessed.
Then you would make your View inherit from the ViewModel, like so:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<MvcApplication1.Models.MyViewModel>" %>
Now in your View, you can access all the different properties of your object simply by writing statements like:
<%= Html.TextBox("MyProperty", Model.MyProperty) %>
To construct your view from your controller, create a new instance of your class (MyViewModel), pass it the ID of the details record that you need, and the logic in your class will take care of getting the right data. Then return your view from your controller like normal.
var myDetailsModel = new MyViewModel(detailsID);
return View(myDetailsModel);
I would recommend reading this primer on ASP.NET MVC
http://weblogs.asp.net/scottgu/archive/2009/04/28/free-asp-net-mvc-nerddinner-tutorial-now-in-html.aspx
It covers most basic scenarios you'll need to get up and running.
If however you want to combine multiple resultsets into one, and then return it as a view, you should create a custom object, and map the resultset to it, then you can bind against your custom object in the view.
When I need to display multiple things like this on a web page, I use typically use RenderAction to do it.
RenderAction allows you to use a controller method dedicated to that particular part of the view (a subview, in effect), so you can pass a single data set of strongly-typed data to that "subview".
RenderAction is in the Microsoft.Web.Mvc ("futures") assembly.
If you are new at all of this, I apologize; this is a bit bleeding edge, but you're going to need to know it anyway. Be sure to check out the NerdDinner tutorial first.
http://www.andreas-schlapsi.com/2008/11/01/renderaction-and-subcontrollers-in-aspnet-mvc/
http://davidhayden.com/blog/dave/archive/2009/04/04/...

Model view presenter, how to pass entities between view?

Edit : Accepted Chris Holmes response, but always ready to refactor if someone come up with a better way! Thanks!
Doing some winforms with MVP what is the best way to pass an entity to another view.
Let say I have a CustomerSearchView/Presenter, on doubleClick I want to show the CustomerEditView/Presenter. I don't want my view to know about the model, so I can't create a ctor that take an ICustomer in parameters.
my reflex would be,
CustomerSearchView create a new CustomerEditView, which create it's own presenter.
Then my CustomerSearchView would do something like :
var customerEditView = new CustomerEditView();
customerEditView.Presenter.Customer = this.Presenter.SelectedCustomer;
Other possible approach would be a CustomerDTO class, and make a CustomerEditView that accept one of those CustomerDTO, but I think it's a lot of work something simple.
Sorry for basic question but all example I can find never reach that point, and it's a brownfield project, and the approach used so far is giving me headache...
I don't know exactly how you are showing your views, so it's a bit difficult to give you specific advice here. This is how I've done this sort of thing before:
What we did was have the CustomerSearchViewPresenter fire an event like OpenCustomer(customerId). (That is assuming that your search view only has a few pieces of Customer data and the customerId would be one of them. If your search view has entire Customer objects listed then you could call OpenCustomer(customer). But I wouldn't build a search view and allow it to populate with entire objects... We keep our search views lightweight in terms of data.)
Somewhere else in the application is an event handler that listens for the OpenCustomer() event and performs the task of creating a new CustomerEditView w/ Presenter (and I'm going to defer to my IoC container do this stuff for me, so I don't have to use the "new" keyword anywhere). Once the view is created we can pass along the id (or customer object) to the new CustomerEditView and then show it.
This class that is responsible for listing the OpenCustomer() event and performs the creation of the CustomerEditView is typically some sort of Controller class in our app.
To further simplify this situation, I've done this another way: I create both the CustomerSearchView (& presenter) and CustomerEditView (& presenter) when the application or module starts up. When the CustomerSearchView needs to open a Customer for editing, the CustomerEditView becomes the responder to the OpenCustomer event and loads the data into itself, and knows how to show itself in whatever container it is supposed to do.
So there's multiple ways to do this.
How about:
//In CustomerSearchPresenter
var presenter = new CustomerEditPresenter();
var customerEditView = new CustomerEditView(presenter);
presenter.SetCustomer(customer);
//In CustomerEditPresenter
public void SetCustomer(customer)
{
View.Name = customer.Name;
View.Id = customer.Id;
...
}
In think your customer search view should just delegate to its presenter you need to have an action execute.
There are a couple of crucial insights to get a natural flow in any MVP code:
It's the presenter that drives the view, not the other way around.
Because of 1. the view need not know about the presenter's existence. Less dependencies usually means easier maintenance.
In C#, I find events being a great asset when decoupling presenters from views. More details in a previous answer: Model-View-Presenter in WinForms
I would look at MS Prism 4, and their nice Navigation interface. Also look at Silverlight and WCF Navigation. They are well done and handle things like prompting the user for confirmation from "dirty" forms, with cancellation.
I would look at the PageFunction() documentation in WCF as well, for how to "call" a page from another, and get back info.
Here's how it works (javascript, sorry):
User double-clicks customer on customer list:
CustomerList.onDblClick(customerId){
app.fireEvent('customerEditRequest', id)
}
...
app.onCustomerEditRequest(id){
this.mainRegion.requestNavigate('customers/edit', id);
}
If navigation to edit view was successful...
CustomerEditView.onNavigatedTo(context){
this.model.load(context.parameters.id));
}
CustomerEditView.onSaveButtonClick(){
this.model.save();
app.fireEvent('customerEdited', id);
}
...
app.onCustomerEdited(id){
app.mainRegion.requestNavigate('customerlist', id);
}
There are a few different ways you could do it:
send a callback function to the edit form, from the customer list. edit form will call it, and you do what you want when it's called.
have the edit form raise on "customerEdited" event that you listen to and react to (no app-wide bus)
use an application-wide Event Bus to manage the events centrally, shown.
I used to have my views communicate with their presenters, but have moved away from that. It doesn't conform to the original definition of a pattern (not a reason in itself for deviating just a contributing factor to exact those benefits). Views ideally should be kept as dumb and with as few dependencies as possible. View should communicate w/ Presenter (any "observers") via delegates/events/some "fire-and-forget" mechanism. As a matter of fact, I've introduced a controller into MVP specifically to intercept View events and either re-fire to presenter (rarely) to communite w/ Presenter, or to communicate with a system or Presenter-specific event bus - enabling me to change user action alerting mechanisms w/out touching the view. Have to be careful with an event bus though; pretty soon you start throwing all events in there, app gets chatty/bogged down in handling events, and events aren't the fastest things in .Net. Sunchronization is an added concern, esp if ur app need to have a more "conversational" interaction with your user.
Should bear in mind that although Presenter is usu view/process-specific, views (and view-models) can be reused; having the View in a containment/delegation relationship with the Presenter strongly couples View/limits its reuse. This could be reduced by some DI, but I find DI containers to be unnecessary complexity in most cases (since I have to know how to create objects anyway and how often do you change out an object for another semantically similar one after creating/testing it?). Concrete dependency goes nowhere except another layer/adds more obscurity/makes things more difficult to debug/trace. Been on a "simplicity" kick lately though, and mostly prefer to do my on Factory/object creations/ORM mappings for most apps, since there's usu a "1-to-1" btw db tables/entities and n need for the added complexity of a generic 3rd-party ORM tool that by taht generic context/needing to serve different apps has to make things harder than they need to be, even if u understand how they work (not the point).
Moreover, it's still quite feasible for View to observe Model in MVP (as in MVC), so I wouldn't be so quick to rule this out. I don't prefer to do this myself, but it' doesn't "break" the pattern. Matter of fact, I developed something similar to MVP about a decade ago because I didnt like the "circular loop" btw the MVC components (View knowing about Model); I preferred to have the cleaner separation btw View and Model that all these patterns (including MVC) professed, as well as a desire to keep View as dumb as possible (observing Model woujld mean View would need more intelligence to process Model changes). What I ended up doing was something like MVVM and strategy patter, where I used "substructures" of the model to pass in to the View, serving as "change notifiers". This kept everything view purpose-specific and flexible/reusable (tough combo).

Categories