I am writing an app using xamarin, mvvmcross, and zxing.net.mobile. I would like to be able to use an instance of IMobileBarcodeScanner in the portable class library to do the scanning.
The issue I'm running into is that the droid version of IMobileBarcodeScanner requires a context to be passed into the constructor. I'm guessing we'd need to register the type in the view constructor so we can pass the correct context.
Since there will be multiple views, would I be able to register a different instance of IMobileBarcodeScanner for each view? Or, could I make the IMobileBarcodeScanner a public property on the view model and set it from the view constructor instead?
Thanks for your help!
There are two main ways I've worked with barcode scanners in the past.
I've launched them as 'new pages' - including using external activities and StartActivityForResult in Android
I've treated them as 'normal controls' - a bit like TextEdit fields within the current page.
When doing the first of these, I generally used a pattern similar to the PictureChooser plugin - on Android, this accesses the current context using IoC in MvxAndroidTask
When doing the second, I treat this purely as a View concern - all the ViewModel needs to provide is an ICommand and/or a string property which can be bound to the scanned event or to the scanned text.
Related
I am tasked with creating a Wizard-Like application that has many Views (UserControls) to load and unload dynamically based on a workflow. From any point in the work flow, I need to be able to jump to another View. In concept, the Wizard will know what View to load next based on the actions performed inside the current View... much like a state-machine.
I am looking for some guidance as to how to get started. This is a WPF desktop application and the current plan is to use Prism and Autofac. I can be swayed in this plan but I'd need to have some good reasoning behind it.
Specifically, does Autofac follow the concept of a ServiceLocator? If not, how do I identify and load the next View?
I expect that my MainWindow will contain one ContentControl and the Content property will be bound to an "ActiveState" property that will hold reference to a ModelView that will be mapped to a View. This ActiveState property will then be changed based on where the workflow sends me.
Thanks in advance for your help.
Specifically, does Autofac follow the concept of a ServiceLocator?
Not sure what you mean, but Autofac supports the CommonServiceLocator. You do not want to use the service locator anti-pattern, though, do you?
If not, how do I identify and load the next View?
Identifying should be the job of your statemachine. Loading it is accomplished through IRegionManager.RequestNavigate. As a side note: you don't need to go view-first, you can also navigate to a view model and have the view as a data template (just in case you're like me and prefer control template + data template over user control).
We are at the preparation on porting a huge windows mobile app to Xamarin
and we are using MvvmCross to help us with the Mvvm.
The application is huge, where workflows live between several pages. So there is a need to pass states/objects between pages. As those states can be big, it does not make sense to serialise them between navigation calls.
My question is: what are any proven or used alternatives to pass objects between view models? Is there some session manager?
Note: we are starting with Android, so maybe there is also good an Android only solution.
Hint: I posted this question on Programmers as well, not sure what's the better platform for this: https://softwareengineering.stackexchange.com/questions/285219/alternatives-on-passing-parameters-from-viewmodel-to-viewmodel-in-mvvmcross
A couple of options I use are:
1) Persist state to a SQLite database and pass an identifier from ViewModel to ViewModel. This is simple and ensures that the state remains even between app restarts.
2) Another option, which is useful in a wizard-like setting is to use a Cache service. I simply created an interface to add and remove entries in a cache by key. I treat it like a standard MvvmCross service and use IoC to inject into my view models. At the start of the process, create a GUID to use as your key, add your state to the cache. Simply pass the key to the next view model, where it can retrieve the state from cache.
In MvvmCross v3 I use ShowViewModel to navigate to different pages. Before converting over to Mvx I'd use the NavigationService.GoBack() method to go back to the previous page. The advantage being that the page isn't re-created.
Since the GoBack method is platform specific to WP, WInRT, Silverlight, what is the best way to handle returning to the previous page so the view model remains platform independent?
One solution might be to use ShowViewModel passing some data that the view can see and then in the case of WP/WinRT, calling RemoveBackEntry from the view. But with Mvx, there's probably a better way.
In MvvmCross v3, we provided a specific mechanism to allow ViewModels to send messages to the UI that they would like to change the current presentation.
This mechanism is ChangePresentation(MvxPresentationHint hint) and it provides routing of messages - presentation hints - from ViewModels to the Presenter.
How the Presenter handles these messages is platform and application specific.
This message mechanism is very general and it might be used for all sort of things in the future - e.g. devs might supply hints which do things like change the UI layout, which highlight part of the UI, which force the user focus on to a certain control, which cause the SIP to be displayed or hidden, etc.
For the case of closing a view model, we have provided a specialisation of MvxPresentationHint - MvxClosePresentationHint - and a helper method in a base class of MvxViewModel:
protected bool Close(IMvxViewModel viewModel)
{
return ChangePresentation(new MvxClosePresentationHint(viewModel));
}
To use this a ViewModel can just call Close(this)
When this is called, the Presenter within your UI will receive a message on the ChangePresentation method:
public interface IMvxViewPresenter
{
void Show(MvxViewModelRequest request);
void ChangePresentation(MvxPresentationHint hint);
}
For the general/typical case - where the ViewModel that is being closed is attached to the view which is the topmost Activity/Page/UIViewController, the default presenters within MvvmCross will be able to handle this message and will be able to GoBack in Windows, to Finish in Android, and to PopViewController in iOS.
However, if your UI is more complicated than that - e.g. if the ViewModel you want to Close actually corresponds to a Tab, to a Flyout, to a SplitView pane, etc, or if the ViewModel corresponds to something other than the current topmost view in the hierarchy - then you will need to provide a custom presenter implementation - and that implementation will have to do platform and application specific logic to handle the Close.
The above hint is what I recommend you use...
However, as an alternative:
If you were to feel this ChangePresentation(MvxPresentationHint hint) mechanism was simply too heavyweight/overkill for your app, then you can also, of course, drop down to a custom or Message based mechanism instead.
One sample that does this is the CustomerManagement sample - it provides a custom IViewModelCloser implementation on each platform - see:
custom interface - https://github.com/slodge/MvvmCross/blob/v3/Sample%20-%20CustomerManagement/CustomerManagement/CustomerManagement/Interfaces/IViewModelCloser.cs
BaseViewModel - https://github.com/slodge/MvvmCross/blob/v3/Sample%20-%20CustomerManagement/CustomerManagement/CustomerManagement/ViewModels/BaseViewModel.cs
Droid - https://github.com/slodge/MvvmCross/blob/v3/Sample%20-%20CustomerManagement/CustomerManagement/CustomerManagement.Droid/SimpleDroidViewModelCloser.cs
WP - https://github.com/slodge/MvvmCross/blob/v3/Sample%20-%20CustomerManagement/CustomerManagement/CustomerManagement.WindowsPhone/ViewModelCloser.cs
Touch - https://github.com/slodge/MvvmCross/blob/v3/Sample%20-%20CustomerManagement/CustomerManagement/CustomerManagement.Touch/CustomerManagementPresenter.cs
I'm not completely sure about mvvmcross, but in MVVM Light what is usually done is to create an INavigationService interface that exposes these methods.
Then, each platform implements this Interface in the platform-specific way (in WP for example by getting a reference to the current frame and its content). This platform specific instance can then do all the correct actions to make sure the navigation pattern is correctly implemented.
Your ViewModels can then get a reference to an instance of the INavigationService through a Dependency Container. That way your VM is independent on the platform specifics of navigation.
I also wrote a blog post on how to use Interfaces to expose a common API for platform specific features: http://www.kenneth-truyers.net/2013/02/24/patterns-for-sharing-code-in-windows-phone-and-windows-8-applications/
The example in the blog post is about Isolated Storage, but the same principles apply to Navigation (or any feature that has different implementations on various platforms for that matter)
I am currently developing a Windows 8 App which contains 2 pages(page1 , page2).
After navigating form page1 to page2,
using this.Frame.Navigate(typeof(AnotherPage));
how can i access the instance of page2 form page1,(We can implement it by having a static instance property and set it when the constructor is called )
But is there any in-build feature to access the current instance of the page from outside of the current page, Or is this pattern of programming is recommended in WinRT paradigms, is there any way to implement my scenario.
First thing is - by default the instance of the previous page is not kept in memory after you navigate to the next page by default - not unless you change the default NavigationCacheMode of the page, which might not be a good idea unless the page takes a lot of time to load and is like a hub page that you go back to a lot.
The approach I would suggest is to use the MVVM pattern, so pages never have to talk to each other and it's the view models that would do it. Then use a pub/sub pattern with a helper like the Messenger class in MVVM Light Toolkit to send weak events/messages instead of adding tight coupling between objects.
All in all - it depends on what you want to do and why you want your pages to talk to each other. You could pass a parameter in the Navigate() call (make sure it's just a primitive type though if you want to support app suspensions using the SuspensionManager class and built-in serialization from the Frame class). You could also use some sort of a global repository or settings service to share data between pages.
If you're not willing to invest in these things - using the plain old static class might be enough for you. Whatever works.
I'm building a little complex prism application. Customer requirements obliges me to utilize ModuleA features in ModuleB.
My question is whether it is breaking prism's decoupling purpose when I reference ModuleA namespace in ModuleB and navigate to its views. If yes then how can I resolve this ?
The two incarnations of the RequestNavigate method (which is the recommended way to begin navigation) intentionally specify views as URIs specifically so that the actual type of the view does not need to be specified inside module code.
Resolution of the actual types from names and of instances from the types is done by the region manager and the container respectively, both of which are configured during the application's bootstrap sequence and do not belong to any specific module.
How exactly are you currently navigating across module boundaries?
You need to use the IEventAggregator and publish/subscribe to weak events (CompositePresentationEvent<TPayload>) through it.
Here is a sample.
Here is the relevant msdn link.