Xamarin.Forms, Inching closer to 100% shared code, write once run anywhere, native apps

Xamarin has finally moved the iOS designer, in Xamarin Studio and the Visual Studio plugin, from the Alpha channel; where I have been using it for the past 6 months into Stable. The less time I have to spend in xCode, the better. Now that it is in stable release (it's been a feature in Xamarin Studio for months), I couldn't be happier to rejoin the masses. And to me, the iOS designer wasn't even the biggest news to come out of Xamarin and the Xamarin 3 announcement.

xamarin forms

Enter Xamarin.Forms

Xamarin has always been good for sharing code and some common business logic. In the past, I have been able to get between 50% to 75% code sharing, with the great MVVMCross I could creep closer to 90%. The rest was writing platform specific UI code, something I have always just accepted.

Not anymore. Xamarin worked with Microsoft on the shared project type to add iOS and Android applications and now we are able to achieve true, 100% code sharing in C#.

Earlier I mentioned my excitement at the iOS designer, there has always been another way to design a UI in Xamarin. Being a WPF kiddie, I have always been a bit intimidated not having a live designer to show me what is going on. Turns out, that is not nearly as intimidating as I thought.

Let's do a quick demo and build a screen:

  • New Solution -> C# -> Forms -> Universal Xamarin.Forms Project (Shared Project) new xamarin solution

  • Notice that the Android and iOS applications are already staged to reference your shared project. solution view

And we already have a very basic shared app.
image of basic shared app

I always like to start off with a bit of organization to ensure that I know where things will go. So I add a Models, Views, and ViewModels folders to the shared project, not the device specific projects.

Let's add a home view (and base view), as well as a viewmodel (and base view model) for our home view. In this instance we will use a master detail application from the forms API.

  • Base Model and NewsItem (model)

    public class BaseModel
    {
        public BaseModel ()
        {
        }
        public string Title {get;set;}
        public string Details { get; set; }
        public int Id { get; set; }
    }    
    
    
    public class NewsItem : BaseModel
    {
        public NewsItem()
        {   
        }
    }
    
  • BaseViewModel and HomeViewModel

      public class HomeViewModel : BaseViewModel
    {
        public HomeViewModel()
        {
               Title = "Football Tournament 2014";
            MyHomeFeed = new    ObservableCollection<NewsItem>()
            {
                new NewsItem(){Title = "Neymar does something"},
                new NewsItem(){Title ="Messi sneezes"},
                new NewsItem(){Title ="Steven Gerrard punches another DJ for not playing Phil Collins"},
            };
        }
        public ObservableCollection<NewsItem> MyHomeFeed {get;set;} 
    }
    
  • And A Home View

    public class HomeMasterView : ContentPage
    {
        private HomeViewModel ViewModel
        {
            get
            {
                return BindingContext as HomeViewModel;
            }
        }
        public HomeMasterView()
        {
            BindingContext = new HomeViewModel();
            var stack = new StackLayout()
            {
                Orientation = StackOrientation.Vertical,
                Padding = new Thickness(0, 8, 0, 8)
            };
    
    
    
        var listView = new ListView();
        listView.ItemsSource = ViewModel.MyHomeFeed;
    
    
        var cell = new DataTemplate(typeof(TextCell));
    
    
        cell.SetBinding (TextCell.TextProperty, "Title");
    
    
        listView.ItemTemplate = cell;
        stack.Children.Add(listView);
        Content = stack;
    }
    
    }

Change the startup page in the App.cs of the Shared Project:

    private static Page homeView;
    public static Page RootPage
       {
        get { return homeView ?? (homeView = new HomeMasterView ()); }
    }

Modify the AppDelegate.cs in the iOS project like so:

     UIWindow window;
    Page page;

    public override bool FinishedLaunching(UIApplication app, NSDictionary options)
    {
        window = new UIWindow (UIScreen.MainScreen.Bounds);
        UINavigationBar.Appearance.SetTitleTextAttributes(new UITextAttributes()
        {
            TextColor = UIColor.White
        });
        Forms.Init();

        page = FootballTournament2014.App.RootPage;
        window.RootViewController = page.CreateViewController ();

        window.MakeKeyAndVisible ();

        return true;
    }

And in the Android application MainActivity.cs

protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);
        Xamarin.Forms.Forms.Init(this, bundle);
        SetPage (FootballTournament2014.App.RootPage);
    }

And that is really it. You now have a Xamarin.Forms application, with 100% shared code! The lack of a UI designer is not at all a hold up for me on this, it just makes sense.

image of andoird and iOS running basic appliaction

I am expanding on this project to get a better understanding of Xamarin.Forms, you can view the source on Github here

comments powered by Disqus