I'm wondering what is the best use of Miguel's GlassButton class in combination with MonoTouch.Dialog? Is there some built in mechanism that would turn a StringElement with attached tap handler into a GlassButton?
Or am I supposed to make custom view elements that inherit/contain the GlassButton?
You can add any UIViews to MonoTouch.Dialog by wrapping UIViews in the UIViewElement, like this:
var myWrapper = new UIViewElement (new GlassButton (rect));
section.Add (myWrapper);
Related
A little confused on how to implement this into my main view controller. The example project shows it as a navigation controller, but I wasn't able to add an existing class on a fresh navigation controller or my current UIViewController. I could just be implementing it wrong though. Much appreciation if I can gain some traction on how to work with these.
If you could share some code that would be great.
How things work:
Navigation Controllers
There are currently 4 different Navigation Controllers that each offer their own features. The controllers can be used individually, or together.
SideNavigationViewController
The SideNavigationViewController offers 3 bodies to display content: mainViewController, leftViewController, and rightViewController.
MainViewController
The mainViewController must always exist, and has a facility for transitioning between view controllers using the transitionFromMainViewController method. Using this method is as easy as passing a UIViewController in its first parameter.
sideNavigationViewController?.transitionFromMainViewController(InboxViewController())
There are further parameters that allow for animations, completions, etc... to be set when transitioning between view controllers.
LeftViewController and RightViewController
The leftViewController and rightViewController can be set only once. To make them dynamic, you would need to use another Navigation Controller as its view controller.
NavigationBarViewController
The NavigationBarViewController offers a NavigationBarView along side the ability to manage two UIViewControllers, the mainViewController and the floatingViewController.
MainViewController
The mainViewController is like the SideNavigationViewController's mainViewController, and has a transitionFromMainViewController method that transitions from view controller to view controller in the body portion of the NavigationBarViewController.
FloatingViewController
The floatingViewController is a modalViewController and when set, it pops over MainViewController and NavigationBarView. Setting that value is like so:
navigationBarViewController?.floatingViewController = InboxViewController()
To close and hide the floatingViewController set it to nil, like so.
navigationBarViewController?.floatingViewController = nil
SearchBarViewController
The SearchBarViewController offers a single transitioning mainViewController, as well, has a SearchBarView at the top. Transitioning the mainViewController is like so:
sideNavigationBarViewController?.transitionFromMainViewController(InboxViewController())
MenuViewController
The MenuViewController is another controller that has a mainViewController, which takes the entire screen. Floating above it, is a MenuView that is used to transition between mainViewControllers.
menuViewController?.transitionFromMainViewController(InboxViewController())
Final Notes
These Navigation Controllers can be used in any combination and any amount of times creating a robust and intricate stack of controllers that act like one.
I hope this helps :)
We try to build an application with a few tabs. As reference-project we use that example: http://slodge.blogspot.co.uk/2013/06/n25-tabs-n1-days-of-mvvmcross.html
To get the ViewModel-instances we need to create the tabs, we used the "HomeViewModel"-pattern as mentioned in that post: Create View Model using MVVMCross built in factory?
What I don't like at this approach is the initialisation of ViewModel's with "new". As far as I understand, it skips the whole ViewModel-Lifecycle (https://github.com/slodge/MvvmCross/wiki/View-Model-Lifecycle) which we really like. In our current project, we'd like to use the "start()" lifecycle-method, but it's never called due to initialisation with "new".
What worked for us was to go that way:
var loaderService = Mvx.Resolve<IMvxViewModelLoader>();
var vm = (UserListViewModel)loaderService.LoadViewModel(new MvxViewModelRequest(typeof(UserListViewModel), null, null, null), null);
So my question: Is that the way to do the job or is it just a dirty workaround and there is a much better solution?
Update: We came to that solution:
CreateTabFor<SettingsViewModel>("Settings", "settings");
//This method loads the ViewModel
private UIViewController CreateTabFor<TTargetViewModel>(string title, string imageName)
where TTargetViewModel : class, IMvxViewModel
{
var controller = new UINavigationController();
controller.NavigationBar.TintColor = UIColor.Black;
var viewModelRequest = new MvxViewModelRequest(typeof(TTargetViewModel), null, null, null);
var screen = this.CreateViewControllerFor<TTargetViewModel>(viewModelRequest) as UIViewController;
SetTitleAndTabBarItem(screen, title, imageName);
controller.PushViewController(screen, false);
return controller;
}
The 'viewmodel lifecycle' is an area of conflicting interests in MvvmCross. The root cause is the conflict between:
viewmodel's which are just the models for any view
viewmodel's which are specifically used within the 'ShowViewModel' navigation process
For simple 'whole page' User Experiences, the C-I-R-S viewmodel lifecycle is easy to support and to ensure it gets consistently used.
However, as soon as the user experience starts to merge in tabs, flyouts, hamburger menus, dialogs, split views, etc then:
the developers sometimes want to control viewmodel lifecycles themselves
it's not as easy for the framework to ensure that view models are always created, activated and tombstoned/rehydrated consistently
Personally, I like your approach - of trying to ensure all viewmodels are independent and all constructed the same way - but MvvmCross doesn't force this approach on all developers.
Specifically for tabs, most of the existing examples do use the 'owned sub-viewmodel' pattern that you've identified.
However, it should be relatively easy to implement other mechanisms if you want to - just as you already have.
In particular, you can:
use the loaderService directly - getting hold of it via Mvx.Resolve<IMvxViewModelLoader>();
use ShowViewModel with a custom presenter to create both views and viewmodels - the beginnings of this is illustrated in that N=25 video but you could take it much further and actually add the tabs in response to ShowViewModel calls.
use alternative calls to create the child tabs and their viewmodels inside the Views - e.g. where the Touch sample currently calls
var screen = this.CreateViewControllerFor(viewModel) as UIViewController;
this could easily be replace with something like:
var screen = this.CreateViewControllerFor<ChildViewModel>() as UIViewController;;
(or one of the other overloads from MvxCanCreateIosViewExtensionMethods.cs)
One repo where I know some users have taken some of these ideas and played with them is the Sliding menu repo - I think they have chosen to use this.CreateViewControllerFor<TViewModel> to create their view models. This may or may not be the way you choose to go - but it might be of interest for you to experiment with.
I am new to MonoTouch from a VS/C# background and am trying to rewrite an existing c# app.
I have made one simple MonoTouch app which succesfully loads data into a List<> from an XML file, and was starting to add Master/Detail code when I discovered the existence of MonoTouch.Dialog which looked like it would make my job much easier. So I started a new project using the sample code at http://docs.xamarin.com/ios/tutorials/MonoTouch.Dialog , changing the basic class to match what I needed.
But I am stuck with trying to prepopulate the DialogViewController with my existing List<>. I have tried using LoadMoreElement but cannot find an example of its use and don't know if it's the best way of doing this.
Thanks Anders.
In the interim period I discovered a different method:
_rootElement = new RootElement ("Riders")
{
new Section()
{
from x in riderList.Riders select (Element) new RootElement(x.Name)
{
new Section()
{
new StringElement("Rider",x.Name),
new StringElement("Club",x.Club),
....
....
...ill try both and see what suits best.
But I'm struggling to find any documentation to describe the methods for the dialog classes, e.g. Section.AddAll() and others used in the link you have provided.
If you want to create a list within an existing dialog view, you can for example create an empty Section and to this section add the list the elements from the list as RadioElement:s or CheckboxElement:s, depending on how many elements you want to be able to select simultaneously.
To facilitate selection, you may need to create a Group/RadioGroup and reference this group when you create the respective list elements in your section.
Here is a quick example of creating a new Section and adding the list elements, assuming that only one element can be selected simultaneously:
var list = new List<SomeClass> { ... };
var listGroup = new RadioGroup("grp", 0);
var listSection = new Section();
listSection.AddAll(list.Select(elem =>
new RadioElement(elem.ToString(), "grp") as Element));
If you want more specialized handling of the elements in the list or the events associated with list actions, you may want to subclass RadioElement or CheckboxElement. There is a good example on how to do this in the answer to this SO question.
I am currently using the advanced editing tableview as outlined in Monotouch.Dialog that allows a user to delete as well as edit the label of table elements. Is there a way to enrich the tableview to achieve something similar to the screenshots, i.e. select one or more elements?
this.TableView.AllowsMultipleSelection = true;
to create something similar to the above i think u need to create a custom element
(maybe a subclass of checkElement)
I'm creating an IPad application using C#, Mono develop and Monotouch.
I've been using Monotouch.Dialog to create functionality similar to the wifi-settings on an iPhone. I'm using StyledStringElement with an accessory and am now trying to differentiate between tapping the row and tapping the DetailDisclosureButton.
I've been found out that I should override the UITableViewDelegate.AccessoryButtonTapped on the UITableView. I've tried to created a derived class from UITableViewDelegate and hook this into the Monotouch.Dialog. But this is where I got stuck. I didn't manage to replace the existing UITableViewDelegate with my extended version.
So my questions are:
Is this the preferred way of handling this event (to be able to differentiate between a tap on the element and a tap on the DetailDisclosureButton) ?
If not, any pointer on how to accomplish this ?
I have been searching the web for a (similar) example but have not found any yet. Any examples that you know of that could get me started ?
Thanks,
boris
event EventHandler accessoryPushed;
public override void AccessoryButtonTapped (UITableView tableView, NSIndexPath indexPath)
{
if(!accessoryPushed)
{
accessoryPushed(this,EventArgs.Empty);
}
}
You will need to add this to the DailogViewController code that you are using (this will override the tapping action). Instead of a simple function, you may want an event to be triggered, so just handle the event in your main code. That is probably your best bet.
Once you change this line, you will have to implement new functions like AccessorySelected (just mimic the path the code follows when a row is selected except with accessory).
On the other hand, you could try a different navigation method, often disclosure buttons are annoying and you don't want to click on them except to get simple information about the button (like a help feature).
I haven't found any other examples, sorry!