Showing posts with label MvvmCross. Show all posts
Showing posts with label MvvmCross. Show all posts

Wednesday, September 23, 2015

How to get connection and carrier information in Windows Phone 8.1 Runtime

Problem:

I have been using the MVVMCross Connectivity plugin for a project.  I went to upgrade the
WP UI to windows phone 8.1 and hit issues immediately.  This is due to the Inversion of Control
layer for Windows Phone in the plugin.  The plugin is using deprecated functionality mainly the DnsEndPoint as part of the Microsoft.Phone.Net namespace.  This is how the plugin is determining if a phone is connected. This requires the change be applied for IsPingReachable method in the Connectivity class in the Windows Phone UI layer for the plugin.

Solution:

Update the connectivity library for MVVMCross with this info

1.) Test for internet connection on Phone

  //Get the Internet connection profile
    string connectionProfileInfo = string.Empty;
    try {
        ConnectionProfile InternetConnectionProfile = NetworkInformation.GetInternetConnectionProfile();

        if (InternetConnectionProfile == null) {
            NotifyUser("Not connected to Internet\n");
        }
        else {
            connectionProfileInfo = GetConnectionProfile(InternetConnectionProfile);
            NotifyUser("Internet connection profile = " +connectionProfileInfo);
        }
    }
    catch (Exception ex) {
        NotifyUser("Unexpected exception occurred: " + ex.ToString());
    }

2.) Get Connectivity properties for Windows Phone 8.1

using Windows.Networking.Connectivity;

/// <summary>
/// Detect the current connection type
/// </summary>
/// <returns>
/// 2 for 2G, 3 for 3G, 4 for 4G
/// 100 for WiFi
/// 0 for unknown or not connected</returns>
private static byte GetConnectionGeneration()
{
    ConnectionProfile profile = NetworkInformation.GetInternetConnectionProfile();
    if (profile.IsWwanConnectionProfile)
    {
        WwanDataClass connectionClass = profile.WwanConnectionProfileDetails.GetCurrentDataClass();
        switch (connectionClass)
        {
            //2G-equivalent
            case WwanDataClass.Edge:
            case WwanDataClass.Gprs:
                return 2;

            //3G-equivalent
            case WwanDataClass.Cdma1xEvdo:
            case WwanDataClass.Cdma1xEvdoRevA:
            case WwanDataClass.Cdma1xEvdoRevB:
            case WwanDataClass.Cdma1xEvdv:
            case WwanDataClass.Cdma1xRtt:
            case WwanDataClass.Cdma3xRtt:
            case WwanDataClass.CdmaUmb:
            case WwanDataClass.Umts:
            case WwanDataClass.Hsdpa:
            case WwanDataClass.Hsupa:
                return 3;

            //4G-equivalent
            case WwanDataClass.LteAdvanced:
                return 4;

            //not connected
            case WwanDataClass.None:
                return 0;

            //unknown
            case WwanDataClass.Custom:
            default:
                return 0;
        }
    }
    else if (profile.IsWlanConnectionProfile)
    {
        return 100;
    }
    return 0;
}
 




Source

  1. https://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh452991.aspx
  2. http://stackoverflow.com/questions/24003786/how-to-get-connection-and-carrier-information-in-windows-phone-8-1-runtime

Friday, September 18, 2015

MVVMCross navigation issues with Windows Phone 8.1 Silverlight - RootFrame_NavigationFailed

Problem:

Had a working Windows Phone 8 project as part of our cross platform solution.  I upgraded the Windows Phone UI to WP Silverlight 8.1.  I immediately began getting strange behaviour on reactivation.

The issue appeared like so.  I can successfully launch the app and it works with no issues.  I then hit the windows button to take me out of the application.  Upon touching the tile to reactivate, the application loads and then crashes.  This does not occur in the previous Windows Phone 8 version.

Issue:

The app activation and deactivation behaves differently in Windows 8.1.  We are using MVVMCross to accomplish our IoC.  Thus for Windows Phone 8, the app.xaml.cs includes an override method in the Application_Launching event which instantiates the IoC to pass control back to the Core for resolution.  This works great in WP8 but due to the changes in navigation in WP8.1, the IoC event does not get called again when the app reloads from memory.  The next issue is that the WP8.1 navigation load overwrites the previous MVVM view in the RootFrame and replaces it with the xaml file specified in the WMAppManifest.xaml file.  This naturally will cause either a crash if you have deleted the MainPage.xaml from your project like I did, or it will load that MainPage.xaml instead of the correct MVVM view.

Solution:


Need to intercept the navigation stack and manually remove the offending page from the stack.
This can be done by going to the App.xaml.cs page in your Windows Phone project.

private void Application_Launching(object sender, LaunchingEventArgs e)
{
      RootFrame.Navigating += RootFrameOnNavigating;
    RootFrame.Navigating += (s, e) =>
    {
    if (e.Uri.ToString().StartsWith("/MainPage.xaml"))
    {
        e.Cancel = true;
    }
    };
}

Source
  1. https://msdn.microsoft.com/en-us/library/windows/apps/ff817008%28v=vs.105%29.aspx
  2. http://stackoverflow.com/questions/23324213/mvvmcross-phone-8-1-resume-shows-mainpage-xaml
  3. http://fetchmytip.blogspot.com/2015/08/mvvmcross-systemreflectiontargetinvocat.html

Tuesday, August 18, 2015

MVVMCross - System.Reflection.TargetInvocationException was unhandled Message: An unhandled exception of type 'System.Reflection.TargetInvocationException' occurred in System.Windows.ni.dll

Problem:


I have my Windows phone project working great with my pcl core.  The MVVMCross libraries are working without issue.  What I have occurring is bug in the UI.  I open my app and run it just fine.  I then hit the windows button which puts the application into background.

When I reactivate the application it crashes with this error:

System.Reflection.TargetInvocationException was unhandled Message: An unhandled exception of type 'System.Reflection.TargetInvocationException' occurred in System.Windows.ni.dll

Solution:

I thought at first it would be an IoC error but it occurs to early for that.  I had to set a breakpoint in the app.xaml.cs in the Windows UI project.  The key was to set it at the Application_Activated event.
Otherwise the crash occurs and it goes straight to the dump.  I was able to walk through the issue until I hit the event RootFrame_NavigationFailed event.  Here I discovered the issue.  I took a look at the e.Exception (e is type NavigationFailedEventArgs).

e.Exception

{System.InvalidOperationException: No XAML found at the location /MainPage.xaml ...

So that was my issue!   The modifications to use MVVMCross means we do not need this page since the setup.cs file does the IoC transfer of the app at startup.  This transfer pushes control down to the PCL layer. My oversight was that the WMAppManifest.xml file has a navigation Page attribute which was set too MainPage.xaml.


NOTE to MVVMCross Users:
What I neglected to do was what Stuart Lodge points out in his N+5 series.  The key event RootFrameOnNavigation in App.xaml.cs needs to handle the IoC redirection.  I did not do this in my Windows project.  Thus the event should include the following code

Fix 1:
private void RootFrameOnNavigating(object sender, NavigatingCancelEventArgs args)
{
args.Cancel = true;
RootFrame.Navigating -= RootFrameOnNavigating;
RootFrame.Dispatcher.BeginInvoke(() => { Cirrious.CrossCore.Mvx.Resolve<Cirrious.MvvmCross.ViewModels.IMvxAppStart>().Start(); });
}

Fix 2:
I continued to have problems due to some code I dropped into the InitializePhoneApplication event.
It says don't touch very clearly!  I did anyway and this was also causing load time issues.  I eliminated my extra code and the method should look like this:

// Do not add any additional code to this method
private void InitializePhoneApplication()
{

            if (phoneApplicationInitialized)

                return;
            // Create the frame but don't set it as RootVisual yet; this allows the splash
            // screen to remain active until the application is ready to render.
            RootFrame = new PhoneApplicationFrame();
            RootFrame.Navigated += CompleteInitializePhoneApplication;

            // Handle navigation failures
            RootFrame.NavigationFailed += RootFrame_NavigationFailed;

            // Ensure we don't initialize again
            phoneApplicationInitialized = true;
}


Now that I have done both of these steps I no longer receive the error.

Source:
  1. https://github.com/MvvmCross/NPlus1DaysOfMvvmCross/blob/master/N-05-MultiPage/MultiPage.Phone/App.xaml.cs
  2. http://mvvmcross.blogspot.com/

Monday, August 17, 2015

MVVMCross Core solution throws error - Unhandled managed exception

Problem:

I just completed the Windows Phone UI project for an MVVMCross solution.  The core project is used by iPhone and Windows Phone UI.  Upon completion of testing for WP, I decided to run a few tests against iPhone which I had completed earlier.  I was immediately confronted with an error -

"An Unhandled exception occurred"

The Xamarin log shows the error occurring at load time.  The compiler built out the bits.  The attempt to run in debug did reveal some more interesting leads. 

[3641:134567] Unhandled managed exception: Could not load file or assembly 'Windows' or one of its dependencies.  The system cannot find the file specified.  (System.IO.FileNotFoundException)

I continued to play around with the changes I had made to the Core PCL.  Then I found the issue.

Solution:

In the course of building the Windows Phone project I used the LongListSelector. This Windows Phone control has several dependcies which are specific to Windows Phone.  The Core PCL included some code which depended on the library Microsoft.Phone.dll.  This reference is not compatible with the Monotouch framework.  My code worked fine when I compiled to Windows Phone but as soon as I tried to run the exe to Monotouch I raised the error. 

My solution was to surround the code with conditional compilation commands

#if USE_MVVMCROSS_WP8

....

#endif

Source:
http://typecastexception.com/post/2012/08/18/Visual-Studio-Use-Conditional-Compilation-to-Control-Runtime-Settings-for-Different-Deployment-Scenarios.aspx

Friday, August 7, 2015

Change Grid/Button Background color through MVVM pattern in Windows Phone

Problem:


Having completed an iPhone app using an MVVMCross core backend.  I need to create the windows phone version UI for the backend.  The iPhone app uses the SegmentControl on a view.  The iPhone app works great and seemlessly with the core.  Now windows phone does not have a segement control per se.  You could simply use a hub/tiles or panorama control templates.  The customer however is very enamored of  the look an feel of the Segment Control.  So it was off too Xaml and blend to build out a similar control.  This I accomplished pretty quickly. 

The issue is the binding to the modelview.  Their is no command property on the grid; however the button control does.  So how to get the interaction to bind with the model view?  Fortunately we have the iValueConverter in the UI layer.  This allows us to bind to properties in the xaml controls.  This combined with model view can allow us to get the functionality to match the segmentcontrol.

Solution:


modelview

private Cirrious.MvvmCross.ViewModels.MvxCommand _myCommand
public ICommand MyCommand
{
             get
            {
                  _myCommand = _myCommand ?? new Cirrious.MvvmCross.ViewModels.MvxCommand(DoMyCommand);
                   return _myCommand;
            }

}

private void DoMyCommand()
{
             ISActive = true;
}


private bool _isActive;

public bool ISActive
{
         get
         { return _isActive;}
         set { _isActive = value;
             RaisePropertyChanged()) => ISActive);
        }

}

view (xaml)

xmlns:phone="clr-namespace:Microsoft.Phone.Controls..."
xmlns:local="clr-namespace:MyNamespace"

<phone:PhoneApplicationPage.Resources>
<local:BrushColorConverter x:Key="ColorConverter" />
</phone:PhoneApplicationPage.Resources>
......

<Grid
Background={Binding ISActive Converter={StaticResource ColorConverter}}
....>
<Button
Background={Binding ISActive Converter={StaticResource ColorConverter}}
Command="{Binding MyCommand}"
.....
/>

</Grid>


(BrushColorConverter.cs (separate class file) in UI project)
 public class ColorConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null)
        {
            return new SolidColorBrush(Colors.Transparent);
        }
        return System.Convert.ToBoolean(value) ?
            new SolidColorBrush(Colors.Red)
          : new SolidColorBrush(Colors.Transparent);
    }
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}




Source:
  1. http://stackoverflow.com/questions/7329812/change-button-background-color-through-mvvm-pattern-in-wpf
  2. http://www.codeproject.com/Articles/758656/Use-Converters-in-your-Windows-Phone-Apps

Wednesday, August 5, 2015

Windows Phone disable status bar

Problem:
Trying to fix a problem on a Windows Phone Silverlight 8.1 app today.  The app starts with a splash screen and do to some extra processing it has an extended screen which simply displays the same screen again.  The issue arises when the splash screen which the OS handles switches over to the first view which also displays the same splash screen image.  Due to the status bar displaying on the first screen the image shifts down.  This leads the image dropping down vice staying in place.  The transition from needs to be smooth without any resizing of the image.  The solution seems to be simply to hide the status bar on that screen.  But how to do it?

Solution:

Windows Phone 8 / Windows Phone 8/8.1 Silverlight


Code behind in ExtendedSplashScreenView.xaml.cs:

public partial class ExtendedSplashScreenView(): MvxPhonePage
{
  InitializeComponent();
  Loaded += MainPage_Loaded;
}

private void MainPage_Loaded(object sender, RoutedEventArgs events)
{
  SystemTray.IsVisible = false;
}


Windows Phone 8.1

Code behind in ExtendedSplashScreenView.xaml.cs:

public partial class ExtendedSplashScreenView(): MvxPhonePage

{
  // Get the Status bar for the Current Window.
  Windows.UI.ViewManagement.StatusBar statusBar =     Windows.UI.ViewManagement.StatusBar.GetForCurrentView();
  // Hides the status bar
  await statusBar.HideAsync();
}


Source:
1.) Windows Phone 8 / Silverlight
  • http://stackoverflow.com/questions/6674627/how-to-hide-the-status-bar-in-wp7-silverlight
2.) Windows Phone 8.1
  • http://blogs.msdn.com/b/johnkenn/archive/2014/04/16/hiding-the-status-bar-in-windows-phone-8-1-apps-or-not.aspx
  •  http://developerpublish.com/how-to-hide-status-bar-in-windows-phone-8-1-xaml-app/
  •  http://blogs.msdn.com/b/amar/archive/2014/05/12/status-bar-in-windows-phone-8-1.aspx

Thursday, July 30, 2015

Unable to read the project file Sqlite.vcxproj

Problem:

 Working with Peter Huene's sqlite port for use with Windows Phone project.  I need to compile the bits for SQLite for the MVVMCross Sqlite libraries.  The project in nuget has support for Droid and Touch but the windows phone project is incomplete.  I downloaded the bits and attempted to open the C++ project and got this wonderful message:

 Unable to read the project file Sqlite.vcxproj

C:\Program Files\Microsoft SDKs\Windows Phone\v8.0\ExtensionSDKs\SQLite.WP80\3.8.6\DesignTime\Common Configuration\Neutral\SQLite.QP80.props not found

Solution:

This made me wonder and about other people with this problem.  Sure enough several people have had similar issues.  The project file checked into the GitHub for Peter's site.  They all resolve down to the version of the Windows Phone extension libraries for SQLite.  Depending on what version is installed.  I was able to resolve the problem by editing the vcxproj file with notepad.  I corrected the path references from 3.8.6 to 3.8.11 which is the version I have installed.  Easy enough and now it works.



Source:
1.) http://stackoverflow.com/questions/18692632/using-sqlite-for-a-windows-phone-8-app
2.)https://github.com/peterhuene/sqlite-net-wp8/issues/9
3.)http://wp.qmatteoq.com/working-with-sqlite-in-windows-phone-8-a-sqlite-net-version-for-mobile/


Thursday, July 16, 2015

plugin not registered for type Cirrious.MvvmCross.Community.Plugins.Sqlite - Unified API

Problem:



I just successfully published the app to the iTunes store.  I had the application written and ready to publish when the wonderful Application Loader refused to load my app to the store!!  Why, because
it was not built to support the Unified API.  Easy fix just use the Xamarin upgrade to Unified Api and voila!  But Unified API is not compatible with MVVMCross SQLite Plugin (v 3.2.2)

Wait, not so fast.  I immediately had problems with the SQLite libraries for MVVMCross. 
This caused me about a week of pain working through all the interdepencies.  I was able to get the latest source code from https://github.com/MvvmCross/MvvmCross-SQLite/issues/39.  Then I built out the bits for support of my project.  I was able to compile and run the app.  It would crash each time I ran and attempted to load the screen which loaded  the sql lite plugin!!!

Error:
plugin not registered for type Cirrious.MvvmCross.Community.Plugins.Sqlite

I wracked my brain as to why the ui failed each time on the sqlite load.  I finally reread the api documentation on the MVVMCross wiki.  It finally hit me when I came across this added requirement for the iOS platform plugin. 



Solution:

You must include a second argument in the bootstrap action for the sqllite plugin.  The bootstrap needs the second argument in the interface constructor for iOS.  If you fail to include it then the path to the Touch plugin then the runtime will not load the plugin and will give you the error.

This is not a problem in Droid or Windows Phone builds.

 
using Cirrious.CrossCore.Plugins; 
using Cirrious.MvvmCross.Community.Plugins.Sqlite; 
using Cirrious.MvvmCross.Community.Plugins.Sqlite.Touch; 


public class SqlitePluginBootstrap 
: MvxLoaderPluginBootstrapAction<Plugins.Sqlite.PluginLoader, Plugins.Sqlite.Touch.Plugin> 
{ }




Source:
  1. https://github.com/MvvmCross/MvvmCross/wiki
  2.  https://github.com/MvvmCross/MvvmCross-SQLite/issues/39
  3. http://stackoverflow.com/questions/30648697/mvvmcross-community-plugin-for-sqlite-with-unified-api 
  4.  http://blog.alectucker.com/post/2015/01/19/sqlite-error-with-xamarinios-unified-api.aspx
  5.  https://bitbucket.org/twincoders/sqlite-net-extensions

Tuesday, June 23, 2015

Localized Strings does not exist in namespace

Problem:
Having completed the iPhone version of our MVVM cross project, we are back to the Windows Phone version.  I created the baseline phone project and added reference to the Core.  Then I built the Windows Phone 8 project and kept getting this error:
The name "LocalizedStrings" does not exist in the namespace

Solution:
Close Visual Studio. Than, delete sub folders 10.0 and 11.0 from "%LOCALAPPDATA%\Microsoft\Phone Tools\CoreCon\" Open Visual Studio and rebuild solution.

Where
%LOCALAPPDATA% = C:\Users\[USER]\AppData\Local

Source:
http://stackoverflow.com/questions/23237549/vs-2013-the-name-localizedstrings-does-not-exist-in-the-namespace

Monday, April 27, 2015

MVVMCross Extended Splash Screen Crossplatform (iOS/Android/WP)

Problem:
Trying to get the splash screen of the application to run longer then the default for each platform.  The typical answer I see posted on most sites is to use the default properties for each of the platform projects.  I wanted something I had more control of.  We are using the MVVMCross pattern for the application and so I wanted to put the solution into the PCL for use on all 3 platforms.  This solution creates a View with the splash screen image which can be extended via the timer function.  This allows us to display the image as long or short as we need it.


Solution:
I found several sites with tips and some hints from Stuart Lodge.  I managed to come up with a solution which builds on some code I found over at the Xamarin developer site.  The timer class should be placed in the PCL of your project.  It can then be referenced by your ModelView and this in turn binds to the View.

1.) Timer Class

using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace iReport.Core
{
 

    /// <summary>
    /// Missing from PCL, except if targeting .NET 4.5.1 + Win8.1 + WP8.1
    /// </summary>
    internal sealed class Timer : CancellationTokenSource
    {
        internal Timer(Action<object> callback, object state, int millisecondsDueTime, int millisecondsPeriod, bool waitForCallbackBeforeNextPeriod = false)
        {
            //Contract.Assert(period == -1, "This stub implementation only supports dueTime.");

            Task.Delay(millisecondsDueTime, Token).ContinueWith(async (t, s) =>
            {
                var tuple = (Tuple<Action<object>, object>)s;

                while (!IsCancellationRequested)
                {
                    if (waitForCallbackBeforeNextPeriod)
                        tuple.Item1(tuple.Item2);
                    else
                        Task.Run(() => tuple.Item1(tuple.Item2));

                    await Task.Delay(millisecondsPeriod, Token).ConfigureAwait(false);
                }

            }, Tuple.Create(callback, state), CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Default);
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
                Cancel();

            base.Dispose(disposing);
        }
    }


}

2.)Model View

using Cirrious.MvvmCross.ViewModels;
using iReport.Core.Services.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;


namespace iReport.Core.ViewModels
{
    public class TimerViewModel : MvxViewModel
    {
        private DateTime? _whenToFinish;
        private Timer _timer;
        public TimerViewModel()
        {
                    _timer = new Timer(OnTick, null, 1000, 1000);
                    _whenToFinish = DateTime.UtcNow.AddSeconds(3);
        }

        #region Timer Test
            private void OnTick(object state)
            {
                if (!_whenToFinish.HasValue)
                    return;

                if (DateTime.UtcNow >= _whenToFinish.Value)
                {
                    base.ShowViewModel<MainViewModel>();

                    _whenToFinish = null;
                }
            }

        
        
        #endregion

    }
}


3.)View


using Cirrious.MvvmCross.Binding.BindingContext;
using Cirrious.MvvmCross.Touch.Views;
using Cirrious.MvvmCross.ViewModels;
using iReport.Core.ViewModels;
using iReport.Touch.Controls;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;

namespace iReport.Touch.Views
{

    [Register("TimerView")]
    public class TimerView : MvxViewController
    {
        private BindableProgress _bindableProgress;


        public override void ViewDidLoad()
        {

            View = new UIView() { BackgroundColor = UIColor.Gray };

            base.ViewDidLoad();

            this.NavigationController.ToolbarHidden = true;
            this.NavigationController.NavigationBarHidden = true;

            UIImage splashscreen = MaxResizeImage(UIImage.FromFile("Default.png", UIScreen.MainScreen.Bounds.Width,UiScreen.MainScreen.Bounds.Height);

             UIImageView splashView = new UIImageView(splashscreen);
             Add(splashView);

            var set = this.CreateBindingSet<TimerView, Core.ViewModels.TimerViewModel>();
           

          
            set.Apply();

        }
    }
 // resize the image to be contained within a maximum width and height, keeping aspect ratio
public UIImage MaxResizeImage(UIImage sourceImage, float maxWidth, float maxHeight)
{
    var sourceSize = sourceImage.Size;
    var maxResizeFactor = Math.Max(maxWidth / sourceSize.Width, maxHeight / sourceSize.Height);
    if (maxResizeFactor > 1) return sourceImage;
    var width = maxResizeFactor * sourceSize.Width;
    var height = maxResizeFactor * sourceSize.Height;
    UIGraphics.BeginImageContext(new SizeF(width, height));
    sourceImage.Draw(new RectangleF(0, 0, width, height));
    var resultImage = UIGraphics.GetImageFromCurrentImageContext();
    UIGraphics.EndImageContext();
    return resultImage;
}



}

Source:

  1. http://stackoverflow.com/questions/5429746/how-to-get-width-and-height-of-iphone-ipad-using-monotouch
  2. http://forums.xamarin.com/discussion/4170/resize-images-and-save-thumbnails
  3. http://forums.xamarin.com/discussion/27327/ios-background-image-scale
  4. http://stackoverflow.com/questions/20447787/system-threading-timer-issue-only-timer-in-mvvmcross
  5. http://stackoverflow.com/questions/15961664/viewmodel-lifecycle-when-does-it-get-disposed
  6. https://code.msdn.microsoft.com/windowsapps/Splash-screen-sample-89c1dc78
 

Wednesday, April 22, 2015

A simple ComboBox for MVVMCross (Xamarin)

Working on getting a "ComboBox" control for our current iOS project.  We are using the MVVMCross libraries by Stuart Lodge.  I am surprised at the relutance of the Apple/Windows to support a simple combo box.  The best iOS option appears to be the UIPickerView.  I found a large number of sample projects and code snippets for straight Objective C and even Xamarin/Monotouch projects. 

A Start...

I was looking for an implementation using the MVVMCross pattern.  I found something very close in https://github.com/MvvmCross/MvvmCross-Tutorials/tree/master/ApiExamples.  The touch project contains the FirstView.cs

Line 144:
public override void ViewDidLoad()
{
base.ViewDidLoad();
var picker = new UIPickerView();
var pickerViewModel = new MvxPickerViewModel(picker);
picker.Model = pickerViewModel;
picker.ShowSelectionIndicator = true;
var textView = new UITextField(new RectangleF(10, 100, 300, 30));
Add(textView);
textView.InputView = picker;
var label = new UILabel(new RectangleF(10, 130, 300, 30));
Add(label);
var set = this.CreateBindingSet<SpinnerView, SpinnerViewModel>();
set.Bind(pickerViewModel).For(p => p.SelectedItem).To(vm => vm.SelectedItem);
set.Bind(pickerViewModel).For(p => p.ItemsSource).To(vm => vm.Items);
set.Bind(textView).To(vm => vm.SelectedItem);
set.Bind(label).To(vm => vm.SelectedItem);
set.Apply();
}

This gets us part of the way there but what this binding does is simply bring up the picker view and displays the 4 options in the Model.  The PickerView contains no way to exit out of the control except using the default back in the iOS navigation bar.  This is not going to work for my use case.  I needed to have a way to close out the pickerview once the selection had been made.

Getting Closer ...

Over at 13daysaweek blog I stumbled across the article Combobox Type Input With iOS and MonoTouch "Combobox Type Input With iOS and MonoTouch".  This is trying to solve the problem I was having but it was not using MVVM.  It was however critical to understanding that the UITextField has two properties which allow a user to associate the pickerview with the textview object.  The properties:
  • TextField.InputView
  • TextField.InputAccessoryView
These properties allow a user to associate the PickerView with the Textbox

"I noticed another interesting property on the UITextField class, InputAccessoryView. It turns out that if a view is assigned to this property, it will be displayed above the view specified by the InputView property. With that in mind, I created a UIToolBar, added a button and set that as the InputAccessorView. "

A Solution ...

So combining both the approaches yielded the following solution


public override void ViewDidLoad()
{
base.ViewDidLoad();
var picker = new UIPickerView();
var pickerViewModel = new MvxPickerViewModel(picker);
picker.Model = pickerViewModel;
picker.ShowSelectionIndicator = true;
var textView = new UITextField(new RectangleF(10, 100, 300, 30));
Add(textView);

UIToolbar = new UIToolbar();
toolbar.BarStyle = UIBarStyle.Black;
toolbar.Translucent = true;
toolbar.SizeToFit();
UIBarButtonItem doneButton = new UIBarButtonItem("Done", UIBarButtonItemStyle.Done, (s, e) =>
{
   //This dismisses the picker view and returns control to the main screen.
   textView.ResignFirstResponder();
}
toolbar.SetItems(new UIBarButtonItem[] { doneButton }, true);

 //This associates the picker view with the textview          
textView.InputView = picker;

//This will insert the toolbar into the pickerview.  This will allow the user to dismiss the
//view once a choice has been made.
textView.InputAccessoryView = toolbar;
var set = this.CreateBindingSet<SpinnerView, SpinnerViewModel>();
set.Bind(pickerViewModel).For(p => p.SelectedItem).To(vm => vm.SelectedItem);
set.Bind(pickerViewModel).For(p => p.ItemsSource).To(vm => vm.Items);
set.Bind(textView).To(vm => vm.SelectedItem);
set.Bind(label).To(vm => vm.SelectedItem);
set.Apply();
}

The toolbar control has been added so that a user selecting from the picker view can close the view once they have selected the value.  This allows the control to be more standalone as it does not depend on the navigation bar as the original code base provided in the MVVM sample.  The critical element in the view is the remember to assign the ResignFirstResponder method to the doneButton action.  If you do not do this then the activation of the done button will not close the PickerView leaving the user stranded on the control.


Source:
  1. https://github.com/MvvmCross/MvvmCross-Tutorials/blob/master/ApiExamples/ApiExamples.Touch/Views/FirstView.cs
  2. http://thirteendaysaweek.com/2012/09/19/combobox-type-input-with-ios-and-monotouch/
  3. https://github.com/13daysaweek/MonoTouchUIPickerView
  4. http://forums.xamarin.com/discussion/5805/uipickerview-example

Friday, March 13, 2015

MVVMCross iOS: How to trigger RowSelected Table View?

I was struggling with how to raise an MVVM event on a click within a tableview.
Fortunately, Stuart Lodge has come through with a great demo of how this all works.
His N+17 video about 47 minutes in gives the details for iOS.  He also has a demo
in his MVVM samples library.  I lifted the pertinent code out of the repo.  The key is to bind
your MVVM command to the SelectionChangeCommand which is a property of the TableView
row item.

Sample:

ModelView:

new Cirrious.MvvmCross.ViewModels.MvxCommand<DilbertItem>((dilbertItem) =>
{   
// note that we can only pass an id here - do *not* serialiase the whole dilbertItem ShowViewModel<DilbertDetailViewModel>(new { id = dilbertItem.Id });
});


View:

// binding
set.Bind(source) .For(s => s.SelectionChangedCommand) .To(s => s.ShowDetailCommand);



Source:
N=17 https://www.youtube.com/watch?v=h0Eww89c9DM&feature=youtu.be&t=47m30s

http://stackoverflow.com/questions/17712589/mvvmcross-ios-how-to-trigger-rowselected-on-a-custom-tableviewsource-using-crea

Wednesday, February 4, 2015

iOS UISegmentedControl custom binding in MVVMCross

Working on a UI screen for an MVVM view using the UISegmented Control.  My view needed to handle the SelectedSegment event which is not part of the MVVMCross libraries.  The good news is that MVVMCross Framework is extensible.  Stuart Lodge did 2 of his N+1 series on this particular subject.  There was some confusion on my part about how exactly to do this until I hit on this stackoverflow post.  The author provided the target binding for the Segmented control with enough hints to get me to the working solution.

Solution:
Create the file MvxUISegmentedControlSelectedSegmentTargetBinding.cs and place it in the Touch project:

1.)MvxUISegmentedControlSelectedSegmentTargetBinding .cs

public class MvxUISegmentedControlSelectedSegmentTargetBinding : MvxPropertyInfoTargetBinding<UISegmentedControl>
{
    public MvxUISegmentedControlSelectedSegmentTargetBinding(object target, PropertyInfo targetPropertyInfo)
        : base(target, targetPropertyInfo)
    {
        this.View.ValueChanged += HandleValueChanged;
    }

    private void HandleValueChanged(object sender, System.EventArgs e)
    {
        var view = this.View;
        if (view == null)
        {
            return;
        }
        FireValueChanged(view.SelectedSegment);
    }

    public override MvxBindingMode DefaultMode
    {
        get { return MvxBindingMode.TwoWay; }
    }

    protected override void Dispose(bool isDisposing)
    {
        base.Dispose(isDisposing);
        if (isDisposing)
        {
            var view = this.View;
            if (view != null)
            {
                view.ValueChanged -= HandleValueChanged;
            }
        }
    }
}

2.)Touch project Setup.cs file needs to register the target factories

protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
{
        registry.RegisterPropertyInfoBindingFactory(typeof(MvxUISegmentedControlSelectedSegmentTargetBinding), typeof(UISegmentedControl), "SelectedSegment");
}
The key here is that the 3rd argument must be match the SelectedSegment property in the UISegmentedControl.

3.)Core project ViewModel needs to include an integer property to bind against the SelectedSegment property. 

ViewModel

private int _selectedSegment

public int SelectedSegment
{
get {return _selectedSegment;}
set
{
   _selectedSegment = value;
   RaisePropertyChanged(); => SelectedSegment;
}


4.)  Touch project View needs to bind the SelectedSegment in the ViewModel to the SelectedSegment in the Mvx control

View Model

public override void ViewDidLoad()
{
....
var segmentControl = new UISegmentedControl();
....
var set = this.CreateBindingSet<View,ViewModel>();

set.Bind(segmentControl).For(sm=>sm.SelectedSegment).To(vm=>vm.SelectedSegment);
...


Source:

1.)mvvmcross-and-uibutton-selected-uisegmentedcontrol-bindings-ios
2.)Stuart Lodge's github repo
3.)MVVMCross N+1 N28 (Custom Binding)
4.)MVVMCross N+1 N19 (Custom Control)
5.)

Wednesday, October 1, 2014

Unauthorized Access Exception - MvxLocationWatcher in Windows Phone 8

I have been working through Stuart Lodge's MvvmCross tutorial.  Session 12 is working with location watchers.  I was able to compile the solution but at run time I received the Unauthorized access error.

Solution:
1.) Solution Explorer
2.) Expand properties of the Windows Phone project
3.) Open WMAppManifest.xml
4.) Capabilities tab
5.) Select ID_CAP_LOCATION check box

The application must grant this permission in order to use the onboard location features.


Wednesday, September 10, 2014

Xaml Binding EventToCommand to MVVM core

I have worked my way through Stuart Lodge's N+1 tutorials.
I was stumped about how to connect my Icommand control from the core to the UI.
Stuart's demo showed how to connect a button or checkbox to the MvxCommand but did not explain how to use the EventToCommand relationship.

I was trying to have a stackpanel fire the event when the user taps it in the UI.
The stackoverflow article provided me the leg up I needed.

I was struggling on which syntax to use to associate a stackpanel in xaml with my command. Turns out I needed to reference the Cirrious namespace in the xaml


xmlns:Commands="clr-namespace:Cirrious.MvvmCross.WindowsPhone.Commands;assembly=Cirriou... xmlns:Commands="clr-namespace:Cirrious.MvvmCross.WindowsPhone.Commands;assembly=Cirrious...

<i:Interaction.Triggers >
   <i:EventTrigger EventName="Tap">
      <Commands:MvxEventToCommand Command="{Binding OnItemTappedCommand}" />
   </i:EventTrigger >
</i:Interaction.Triggers>
Source:
http://stackoverflow.com/questions/16823444/im-getting-build-errors-when-using-mvxeventtocommand-within-a-wp8-project

https://github.com/MvvmCross/MvvmCross/blob/e6d10972b5c28e00e80acc3d9e8910961aa813d6/Cirrious/Cirrious.MvvmCross.WindowsPhone/Commands/MvxEventToCommand.cs


iPhone development in C#

Starting a project to develop an iPhone application.  We are going to pursue a cross platform solution using Xamarin software.  This should allow us to write the core processes in C# and deploy UIs specific to the platform we are targeting.  In order to get the most out of the design, we are going to use the MVVM pattern.  MVVMCross is a github project which used in concert with Xamarin software will allow us to write C# for both back end and UI.

This promises to be an exciting project.  We currently have 2 versions of the application written (WP8, Android).  These were done without the benefit of this approach and will at some point be migrated to this pattern. 

Wednesday, September 3, 2014

MVVMCross - Could not install package 'MvvmCross.PortableSupport 3.1.1'.

MVVM Cross nuget package 3.1.1 with VS 2012 SP2 not working

Error:

Could not install package 'MvvmCross.PortableSupport 3.1.1'. You are trying to install this package into a project that targets 'portable-net45+sl40+wp+win', but the package does not contain any assembly references or content files that are compatible with that framework. For more information, contact the package author.

Explanation:

The problem is that MvvmCross.PortableSupport 3.1.1 has a portable class library that targets:
portable-win+net45+sl50+wp8+MonoAndroid+MonoTouch
Whilst your portable class library project is targeting:
portable-win+net45+sl40+wp71
The MonoAndroid and MonoTouch frameworks are optional and will not be used in the comparison if you are using NuGet 2.7.2 or above. Your project is targeting Silverlight 4.0 and Windows Phone 7.1 whilst MvvmCross.Portable is targeting Silverlight 5.0 and Windows Phone 8. So it is not compatible. You cannot install a portable class library into a portable class library project that targets older framework versions. You will need to change the profile for your portable class library project so that it targets these frameworks.


Solution:


Option 1:

Target Frameworks
.Net 4.5, Silverlight 5, Windows Phone 8, Windows Store apps (Windows 8)


Option 2:

The workaround mentioned on a comment on Stuart's blog (at http://slodge.blogspot.co.uk/2013/04/n0-first-mvvmcross-application-n1-days.html) worked for me:
Remove Mono for Android, MonoTouch, VS MonoTouch and Windows Phone from the Target Frameworks in the Core project properties. Install MvvmCross NuGet package. Add the Target Frameworks back in.

Wednesday, July 23, 2014

Xamarin and Sole Source justification

Great post by Tim Anderson and Andy Dent about Xamarin vs. other competitors

- Xamarin (+ MVVMCross) ideal cross product solution. https://github.com/MvvmCross/MvvmCross

- The purpose of PhoneGap is to allow HTML-based web applications to be deployed and installed as native applications

- The goal of Titanium Mobile is to provide a high level, cross-platform JavaScript runtime and API for mobile development (today we support iOS, Android, and the browser, with BlackBerry 10 and Windows Phone coming soon and eventually, respectively).


Source:

http://stackoverflow.com/questions/17249500/xamarin-2-0-vs-appcelerator-titanium-vs-phonegap