2

I am refactoring an app using MvvmCross and I am in the midst of getting a Settings View to show on the three platforms: WP7, Android and iPhone. I have created a SettingsViewModel which holds two lists. One with Update Frequencies to poll a server and another one with information for which server to poll. These are called UpdateFrequencies and PublicSites. The two lists each have a property in the SettingsViewModel to determine which UpdateFrequency and which Site has been selected, UpdateFrequency and SelectedSite.

On WP7 this data is bound to a ListPicker like this:

<toolkit:ListPicker 
    Name="UpdateFrequencies"
    ItemsSource="{Binding UpdateFrequencies}"
    SelectedItem="{Binding UpdateFrequency, Mode=TwoWay}"
    Header="Real-time data update frequency"
    />

SettingsView WP7

Similarly on Android it is bound to a Spinner like this:

<cirrious.mvvmcross.binding.android.views.MvxBindableSpinner
    android:id="@+id/SpinnerUpdateFrequencies"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    local:MvxDropDownItemTemplate="@layout/spinneritem_updatefrequencydropdown"
    local:MvxItemTemplate="@layout/spinneritem_updatefrequency"
    local:MvxBind="{'ItemsSource':{'Path':'UpdateFrequencies'},'SelectedItem':{'Path':'UpdateFrequency','Mode':'TwoWay'}}"
    />

SettingsView Android

Now I am trying to do the same on iPhone and I just can't seem to wrap my head around how to bind it in a similar fashion. I have been looking through all the samples I could find and cannot seem to find something similar. Can someone maybe point me in the correct direction?

Cheesebaron
  • 24,131
  • 15
  • 66
  • 118
  • You're right - this hasn't been done yet as a reusable control. I'm sure somewhere in the dialog code I implemented a uipickerview binding (somewhere in https://github.com/slodge/MvvmCross/tree/master/Cirrious/Cirrious.MvvmCross.Dialog/Dialog/Elements) but for the life of me I can't find it right now. I'm on mobile only hookup for 2 more days - on vacation- can take a look properly when back. If you need to implement this then a textfield and picker view combo is the way to go. It can be bound quite quickly... But I don't think it's available 'ready built' right now. – Stuart Aug 29 '12 at 19:27
  • I still can't find it, so it must be in a customer project somewhere. If you need this in a hurry, then you can always just write 'normal' IOS code, just hook up to the properties like ViewModel.UpdateFrequency as needed inside ViewDidLoad - and to the ViewModel.PropertyChanged event if needed too. – Stuart Aug 29 '12 at 19:37

2 Answers2

2

The mvvmcross ios source doesn't currently include this - so you'll need to write your own.

If you're working with monotouch dialog, then this means you'll need to create a new element type and use this to display both a static text field (the current value) and a picker view (the list of choices).

The good news is that this is quite similar to what the current TimeElement and DateElement do - so you can use one of those as a starting template. To adapt this template, you'll need to:

  • change it so that the Value is based on a String rather than a DateTime
  • add a List public property - which will be the list of Choices. As this is public and a property, it can be automatically used for data binding.
  • adapt the Selected handler so that the Element displays a simple text based picker view rather than a date or time picker view when tapped - head over to wally's blog for info on using a pickerview (http://weblogs.asp.net/wallym/archive/2010/01/07/uipicker-in-the-iphone-with-monotouch.aspx) - or follow the advice from @r4j above
  • add a picker view model that shows the correct values (from Choices), that defaults to the current Value, and that sets the Value when the picker is done (setting the Value will cause the bound ViewModel property to also be updated).

This approach does assume that the Value and the Choices list won't change while the Picker is displayed - but that's a very safe assumption for most uses.

Sorry, I can't provide sample code (or an addition to the library) right now. If someone else doesn't beat me to it, then I'll try to add one when I'm back on a dev box in a couple of days from now.


As an extra idea, one alternative approach to providing a ui for these settings is to try to use the radio/radio group approach within monotouch.dialog. However, I'm afraid this would also require a little new Element work - as the current radio implementation isn't set up to work with (bind to) a list of choices dynamically. When I get time, I'll look at adding this too - as I think it would be a very useful addition.

Stuart
  • 66,722
  • 7
  • 114
  • 165
  • I think I got the UIPickerView bound now, it seems to work. Though some quirks I experience with all MonoTouch.Dialog elements, is that the bindings on all elements I create, BooleanElement, StringElement etc. do not update the ViewModel, maybe that is a new Issue, or is that correct behaviour? Btw. my implementation of the PickerElement can be found here: https://gist.github.com/3552565 – Cheesebaron Aug 31 '12 at 13:23
  • Would be cool with some code that resized the components automagically, but that is something that I will have to look at in the future. Right now they are defined manually like in all the samples I could find on how to use UIPickerView. Make sure that SelectedRow is not null when dumping data into the PickerElement. Will write a sample soon! – Cheesebaron Aug 31 '12 at 13:25
  • Thanks - looks good and looks like it was quite a lot of work! The bindings should update the viewmodel - that's how some of the samples work - eg Entryelement and FloatElement in https://github.com/slodge/MvvmCross/blob/master/Sample%20-%20SimpleDialogBinding/SimpleBinding/SimpleBindingDialog/TipView.cs - but you do need to explicitly set Mode to TwoWay - blame Microsoft for the OneWay default value :) – Stuart Aug 31 '12 at 15:37
1

iOS doesn't have anything like dropdown list or listview. I had the same problem with you.
Here is my try:

  • Create a UITextField, binding data for it as selected item.
  • Fire event TouchDown for this TextField. When user touch in it, transfer to another view (call View2).

  • In View2, create a TableView that binding list data from ViewModel. When user select an item, go back previous view, update UITextField with new selected item.

Hope this help!

Update:
As you mention, I forgot UIPickerView. But I think UIPickerView takes up too much space.
I did this before: use a UITextField, when user touch in, show a actionsheet with a picker view, select an item, then update UITextfiled.
I recommend actionsheet because you can put a cancel, done button in it where user can cancel or choose an item.
Here is an example from xamarin which use an ActionSheetDatePicker

ductran
  • 10,043
  • 19
  • 82
  • 165
  • Well iOS kind of has something similar. The UIPickerView, which can be used like a dropdown, although no bindings are present for it. – Cheesebaron Aug 29 '12 at 14:39
  • Brilliant, I forgot this guy. But I recommend using a UIPickerView with an actionsheet where you can put an cancel or done button. Please check my updated answer – ductran Aug 29 '12 at 15:42