Is there a way to find the startviewmodel in MVVMCross? - mvvmcross

I have done a RegisterAppStart<FirstViewModel>() in the Core App.cs, now I navigate to FirstViewModel, then SecondViewModel and finally ThirdViewModel using ShowViewModel(),
Is there a way I want to navigate to the viewmodel which has been registered using RegisterAppStart<>(), I mean is this persisted or saved somewhere during run?
All I want is to get this value at runtime.

If you want to use a singleton instance of a view model then you can do this using a custom view model locator - see the wiki - https://github.com/MvvmCross/MvvmCross/wiki/Customising-using-App-and-Setup - "overriding view model location and construction"

Related

MvvmCross 4 support for UWP, AppShell missing Frame

I have created a new solution for my MvvmCross app that supported Windows Store and I want to support UWP on Windows 10. I have moved over the PCL successfully, but I am having problems getting the basic UWP app working using a sample provided by MS (NavigationMenu) which uses the SplitView and the AppShell pattern they are recommending for the new navigation/command model. I referenced a helpful blog post (http://stephanvs.com/implementing-a-multi-region-presenter-for-windows-10-uwp-and-mvvmcross/), which gave me some guidance on how to integrate mvvmcross into the AppShell, but startup is failing because the AppShell does not have a valid Frame defined. Frame is a read-only property, and I have been unable to see where this is being set up.
I am using the standard AppShell implementation from the NavigationMenu with the following changes as recommended in the blog post:
public sealed partial class AppShell : MvxWindowsPage // was Page
public Frame AppFrame { get { return this.Frame; } } // was this.frame
Except for code after the error, there are no differences in the setup. In looking at the MvxWindowsPage implementation, there doesn't seem to be anything special as it still invokes the Page initialization. Is there something obvious I am missing?
So the link to the blogpost is correct, in other words you'll need to use MultiRegions from MvvmCross to get this working.
But what the blogpost doesn't show is a complete working version...
I've added one on my github here:
https://github.com/Depechie/MvvmCrossUWPSplitView
Some pointers to take away, like I said in the comments.
Your view where the SplitView will be present, needs to have a property to return a valid Frame to look for while injecting new views. This can be returned like this return (Frame)this.WrappedFrame.UnderlyingControl; found in the code here https://github.com/Depechie/MvvmCrossUWPSplitView/blob/master/MvvmCrossUWP.Win/Views/FirstView.xaml.cs#L13
Than all views you want to load up in the SplitView will need to reference to the region you defined in that SplitView, in my case I named it FrameContent as seen here https://github.com/Depechie/MvvmCrossUWPSplitView/blob/master/MvvmCrossUWP.Win/Views/FirstView.xaml#L48
So use that name for the region attribute in all to be loaded views like so [MvxRegion("FrameContent")] example here https://github.com/Depechie/MvvmCrossUWPSplitView/blob/master/MvvmCrossUWP.Win/Views/SecondView.xaml.cs#L7
I see what you're trying to do with the SplitView template that's provided by Microsoft. There is however a mismatch between things managed by MvvmCross and UWP.
By default MvvmCross maps ViewModels to Views based on naming conventions. What you are trying to do is use a view 'AppShell' (which is derived of Windows.UI.Xaml.Controls.Page) that doesn't adhere to the default MvvmCross convention.
The way I choose to implement this SplitView (Hamburger) functionality is by deleting the provided AppShell class entirely. I then created a new view named HomeView (since I have a ViewModel with the name HomeViewModel) and added the SplitView control there as described in the post you mentioned above.
For completeness I've created a Gist with the App.xaml.cs and HomeView.xaml as you requested. You can find them here: https://gist.github.com/Stephanvs/7bb2cdc9dbf15cb7a90f

Yii2 access to actions in new controllers

Comrades, I have had issues implementing yii2 basic but I'm yet to give up. I have successfully installed yii2, activated pretty url and created the .htaccess file in the root folder. The Home, About, Contact and Login urlswork fine.
i. I have created a new model, InstTypes with the CRUD. Why does http://localhost:8081/we#ss/instTypes/create return Not Found (#404)?
ii. I have also created a module instClients. I can access the index action in the DefaultControler. I have a model Insts with its CRUD under this modules. Why does http://localhost:8081/we#ss/instClients/insts/create return Not Found (#404)?
I tend to think that this could be due to the removal of the import and autoload from the config.
Could someone demonstrate how they've created a new model and CRUD and successfully accessed its actions?
Thanks in advance
I have created a new model, InstTypes with the CRUD. Why does
http://localhost:8081/we#ss/instTypes/create return Not Found (#404)?
You cannot access a model directly, the only way to interact with a model is via a controller which will intern interact with the model and the view. By initializing the model $model = new YourModelNmae(); or by rendering a view.
From your URL
http://localhost:8081/we#ss/instTypes/create
InstType should be your controller while create is an action under InstType
Using Yii2 Gii tool to generate a CRUD do the following : -
Generate your model
Generate your CRUD
go to
http://localhost:8081/we#ss/yourController/YourActionOnYourController
Refer to this youtube link for more detail https://www.youtube.com/watch?v=6B52-li6IgU
Happy coding :)
Just to add to the other answers, your url isn't working because it's camelCase. You need to make it hyphenated, so
http://localhost:8081/we#ss/instTypes/create
will become
http://localhost:8081/we#ss/inst-types/create
You're getting the 404 because you're trying to access instTypes, it should be inst-types.
this solved my problem. I needed to add the controllers to the controller map.

Mvvmcross, how to access a ViewModel from my android project

I have an Android app which uses a SupportActionBar that contains a bunch of tabs. These tabs each have a fragment that in turn are connected to a ViewModel in my core project. This works great and when i start the app they are all initialized right away and setup correctly.
What i would like to do is to call on a method on one of these ViewModels from my main activity that contains all the tabs and fragments.
I read in another post that in WP you could cast the DataContext to the ViewModel but that might not work in Android. I haven't been able to do this, maybe because my DataContext is not the currently displayed ViewModel but the MainViewModel connected to my main activity. Or maybe it's not supposed to be done that way, i'm not sure.
I'm trying to do this:
var test = (MessagesViewModel)this.DataContext;
test.GetViewDataFromApi();
To update the data in the view when i press the tab. I can't use the Init function for this for example since the ViewModel isn't recreated everytime i show the view.
Are you trying to update some data in the tab's fragment when tab is selected?
If that's the case, one way to do it is to
1) handle the tab selection event to get the current tab(maybe using TabListener),
2) get the fragment (MvxFagment) in the selected tab
3) get the (IMvxViewModel) view-model from the fragment
4) call the method you need to update data on the view-model
I assume you are using a MvxFragment (https://github.com/MvvmCross/MvvmCross/blob/v3.1/Cirrious/Cirrious.MvvmCross.Droid.Fragging/Fragments/MvxFragment.cs?source=cc) so you can access the view-model from the MvxFragment's ViewModel property.

Angular - building a "public" function (newbie)

I'm After several days learning angularJS through converting my standart JS app to a ng one.
I was wondering about this simple scenario:
I have a global function called fb_connect(),
it can be used from any page (or any controller if you like) to make a facebook-based login.
This function makes a simple http call and receives a JSON object contain data to move on (display a pop up, login, etc...)
I read that I can define a Factory or a Service for my app and use it in any controller, which works fine.
So, I created a fb_connect factory function.
The problem is that now, in every page (every controller), I have to define that fb_connect in the constructor of every controller - for example :
function welcome($scope,fb_connect){});
What is the proper way to do this kind of actions using Angular without having to define these functions each and every time in every controller?
Thanks
Setting up factories and services is all part of the dependency injection system of Angular. Using that system is great when you need to create things that depend on other injected things. It's a big tree of dependencies. It's also nice for creating singletons, such that everywhere in your code end up using the same instance of some object.
It sounds to me like neither of these benefits apply in your case. I'd suggest just not using Angular's DI for it. You have some function defined globally, just call it directly and skip the DI. There's nothing wrong with that.
Of course you say it makes an Ajax call, so doesn't depend on the Angular $http service?
Your two options are:
Declare the function on the $rootScope
Inject it as a service
My advice is to go with making it a service. The whole purpose of services is explained in the Angular.js docs, just like this quote:
Angular services are singletons that carry out specific tasks common to web apps... To use an Angular service, you identify it as a dependency for the dependent (a controller, or another service) that depends on the service.
As you mentioned in your question, you'd prefer to not define the service in every controller you wish to use it in. With $rootScope you'll be injecting that also in every controller. So really it's a question of which you prefer, although to answer your question, the proper way of using a factory or service is to inject it into the controller you wish to use it in.
You can always put it in the $rootScope
myApp.run(function($rootScope, fb_connect){
$rootScope.welcome = function(){
};
});

Model view controller

I have a tree control in my GUI (with naturally lots of GUI/platform specific functions to handle the nodes).
I have a data model with its own complex set of nodes, children, properties etc..
I want the tree to display a representation of the model, be able to send messages to the nodes inside the model and be told to redraw itself when the model changes.
But I don't want the GUI code to need to know the details of the model's data types and I don't want to pollute the model by linking it to the GUI classes.
I can't get my head around how the controller is supposed to do this and what functions it should provide?
(this is in C++ but that shouldn't matter)
GUI "controls" don't quite fit neatly into a model-view-controller pattern because they typically have their own internal model rather than accepting a reference to one. If the control is structured that way, you'll need an adapter class that "data-binds" the control's internal model to the underlying data model.
This can accomplish something similar to what model-view-controller would, except that the adapter class plays the role both of a view hookup component (updating the GUI from the data model) and a controller (interpreting GUI events into model actions).
Qt provides a group of classes for model-view programming. You can hook a tree view to a filesystem model, for example, and neither directly know anything about each other (except a pointer to the model in the view).
Your requirements are:
Tree displays representation of model
Nodes in tree can send messages to nodes inside model
Tree redraws itself based on model changes
I don't know exactly what kind of data you're working with here, but a hierarchical model is a fairly simple thing. I'll take it as a given you know how to iterate hierarchical data and populate a tree view.
Your controller should have member function(s) for sending messages to the model. The parameters should be a model element and the message you want to send. This way, the UI is completely unaware of how the message gets to the element, but can get the messages through.
The last requirement is more tricky, and depends on a few things (e.g., the lifetime of the controller, application architecture, etc.) I'm going to assume the controller lives as long as the tree view does. If that's the case, then your controller should provide a way to set a callback on model changes. Then, when the controller changes the model, it can callback to the UI without being aware of the UI.
i think your troubles start with an unfortunate choice of words. the 'control' thingies doesn't have anything to do with the 'controller' in MVC. that's why some GUI libraries use other names (widgets is a common one).
your 'tree control' is the view, not the controller. it should be tied to the GUI, both for display, and to get GUI events and turn them into 'tree events'.
the controller gets those 'tree events' and does the necessary modifications to the model. that's where you couple the 'action' with the 'response'.
First Solution: You can implement a "Subject observer" pattern between model and view, with model as the subject and view as the observer. Whenever there is a change in the state of model, it can fire a event to all the observers those are registered, they can update themselves.
Second Solution: Introduce a controller, which registers with model as observer. Upon receiving a event for update from Model, it can update the view. Even you can decouple view from controller using one more subject observer pattern between controller and view
Third Solution: Use MVP pattern. Model view Presenter. This pattern used whenever there is no much computation in controller i.e., job of the controller is just to update its corresponding view. Here controller becomes Presenter.
You need a controller that sits outside the display widget but has the state of the tree (in MFc there are CTreeView/CTreeCtrl classes - there is a similiar separation in Qt) the tree controller handles all the data storage and calls redraws on the tree widget.
Changes in the tree widget get sent to the tree controller - so this controller needs to know about the gui functions.
The model will need set/get functions for all the relevant parameters for the nodes. But these can return simple types so aren't dependent on the gui.
Updating the view form the model requires sending a message, if you don't want the model to know about your gui messaging the best you can do is register a callback function (a void pointer to a function) from the tree controller - and call this to do an update.
This update function can then query the model for the changes.