Android.Kotlin – Create a TabLayout

We’ll once again take a break from the cross-platform Xamarin content and look at an example of using the latest Kotlin language from Jetbrains with our native Android applications. In this post, we’ll look at an implementation of a TabLayout with a ViewPager using Kotlin!

I also apologize for the lack of useful highlighting of the Kotlin code in this post. Since it is a new language, WordPress doesn’t support it as well for code snippets…

The source code for this example can be found on my GitHub here:
https://github.com/SuavePirate/KotlinPuppies.

The Layout

This example will use a RecyclerView for the content of each Fragment. So we need to define layouts for our Puppy, Fragment, and our entire Activity that houses the TabLayout and Fragments.

Our puppy item will contain a CardView that has an image and text to contain a picture of the puppy and the pup’s name!

puppy_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="8dp"
        app:cardElevation="8dp">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="16dp"
            android:orientation="vertical">

            <ImageView
                android:id="@+id/puppyImageView"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:srcCompat="@mipmap/ic_launcher" />

            <TextView
                android:id="@+id/puppyTextView"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textAlignment="center"
                android:text="Puppy Name" />
        </LinearLayout>

    </android.support.v7.widget.CardView>
</LinearLayout>

Now let’s look at our Fragment layout that will contain a RecylerView that houses each collection of puppies.

puppy_fragment.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.suavepirate.kotlinpuppies.MainActivity$PlaceholderFragment">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/puppyRecyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        tools:listitem="@layout/puppy_item" />
</RelativeLayout>

Now let’s wrap it all together with our main layout:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="com.suavepirate.kotlinpuppies.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="@dimen/appbar_padding_top"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|enterAlways"
            app:popupTheme="@style/AppTheme.PopupOverlay">

        </android.support.v7.widget.Toolbar>

        <android.support.design.widget.TabLayout
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </android.support.design.widget.AppBarLayout>

    <android.support.v4.view.ViewPager
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />


</android.support.design.widget.CoordinatorLayout>

Now that we have our layouts, let’s create our Fragment, Adapters, and then wrap it all together in our MainActivity.

Building the Recycler Adapter

Let’s first define our RecyclerView adapter and ViewHolder to contain our collections of puppies.

PuppyHolder.kt

class PuppyHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    private val puppyImage: ImageView = itemView.findViewById<ImageView>(R.id.puppyImageView)
    private val puppyName: TextView = itemView.findViewById(R.id.puppyTextView)

    fun updateWithPuppy(puppy: Puppy) {
        puppyImage.setImageDrawable(puppy.imageFile)
        puppyName.text = puppy.name
    }
}

This code defines a class that inherits the RecyclerView.ViewHolder with a default constructor that requires a View parameter that is also passed into the base class constructor. It then defines the two subviews we need to populate – the TextView and ImageView of a single puppy. Lastly, we create our updateWithPuppy function that will be called by our Adapter to instantiate the content with the given puppy’s information.

Now that we have our ViewHolder, we can create our Adapter:

PuppyAdapter.kt

class PuppyAdapter(private val puppies: ArrayList<Puppy>) : RecyclerView.Adapter<PuppyHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PuppyHolder {
        val puppyItem = LayoutInflater.from(parent.context).inflate(R.layout.puppy_item, parent, false) as LinearLayout
        return PuppyHolder(puppyItem)
    }

    override fun onBindViewHolder(holder: PuppyHolder, position: Int) {
        holder.updateWithPuppy(puppies[position])
    }

    override fun getItemCount(): Int {
        return puppies.toArray().count();
    }

}

This adapter uses another cool feature of Kotlin – Defining a private field in the constructor while also auto-setting it. The class declaration and default constructor of PuppyAdapter(private val puppies: ArrayList) is the equivalent to something like this in Java:

public class PuppyAdapter{
    private final ArrayList<Puppy> puppies;
    public PuppyAdapter(ArrayList<Puppy> puppies){
        this.puppies = puppies;
    }
}

That’s pretty sweet! The rest of the wire up for the Adapter is pretty standard. It sets the ViewHolder using the PuppyHolder we created above and updates it with the puppy by finding it with the given index.

The Puppy Fragment

Now we can create our Fragment that will contain and wire up the RecyclerView for each puppy collection.

PuppyListFragment.kt


class PuppyListFragment(passedContext: Context) : Fragment(){

    val puppyFactory : PuppyFactory = PuppyFactory(passedContext)
    val ARG_LIST_TYPE = "LIST_TYPE"
    val passThroughContext : Context = passedContext


    override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        val rootView = inflater!!.inflate(R.layout.fragment_main, container, false)
        val recyclerView = rootView.findViewById<RecyclerView>(R.id.puppyRecyclerView) as RecyclerView
        val listType = this.arguments.getSerializable(ARG_LIST_TYPE) as PuppyListType
        var puppies = ArrayList<Puppy>()
        when (listType) {
            PuppyListType.All -> puppies = puppyFactory.puppies
            PuppyListType.Active -> puppies = puppyFactory.activePuppies
            PuppyListType.LeashTrained -> puppies = puppyFactory.leashTrainedPuppies
            PuppyListType.Big -> puppies = puppyFactory.bigPuppies
            PuppyListType.Small -> puppies = puppyFactory.smallPuppies
        }

        recyclerView.adapter = PuppyAdapter(puppies)
        recyclerView.layoutManager = LinearLayoutManager(passThroughContext)
        return rootView
    }

    companion object {
        val ARG_LIST_TYPE = "LIST_TYPE"

        fun newInstance(listType: PuppyListType, context: Context): PuppyListFragment {
            val fragment = PuppyListFragment(context)
            val args = Bundle()
            args.putSerializable(ARG_LIST_TYPE, listType)
            fragment.arguments = args
            return fragment
        }
    }


}

In the onCreateView override, we get our puppies by type from our factory class and then instantiate our PuppyAdapter and LinearLayoutManager that get applied to the RecyclerView that we grab from our layout created earlier. Now we can pass in the PuppyListType that the fragment is responsible for displaying which will then set up our RecyclerView to render those particular puppies.

We also set up what is the equivalent of a static function that can instantiate a new instance of a PuppyListFragment by using a nested companion object.

Adding Page Adapter

Now that we have our Fragment and it’s child RecyclerView for puppies all set up, we can now create an adapter that is responsible for handling the different pages within the TabLayout that we are ultimately setting up.

PageAdapter.kt

class PageAdapter(fm: FragmentManager, private val context: Context) : FragmentPagerAdapter(fm) {

    override fun getItem(position: Int): Fragment {
        when (position) {
            0 -> return PuppyListFragment.newInstance(PuppyListType.All, context)
            1 -> return PuppyListFragment.newInstance(PuppyListType.Big, context)
            2 -> return PuppyListFragment.newInstance(PuppyListType.Small, context)
            3 -> return PuppyListFragment.newInstance(PuppyListType.LeashTrained, context)
            4 -> return PuppyListFragment.newInstance(PuppyListType.Active, context)
        }
        return PuppyListFragment.newInstance(PuppyListType.All, context)
    }

    override fun getCount(): Int {
        // Show 5 total pages.
        return 5
    }

    override fun getPageTitle(position: Int): CharSequence? {
        // return null to show no title.
        return null
        
    }

}

This is a pretty standard implementation of a PageAdapter. We override the getItem function and return the appropriate instantiated PuppyListFragment by passing in the PuppyListType we want to use by the grouping.

Set up the Activity

The last bit now is the set up our Activity that will house our TabLayout and ViewPager that will contain multiple instances of the PuppyListFragment to show different collections of puppies by category.

MainActivity.kt



class MainActivity : AppCompatActivity() {
    private var mSectionsPagerAdapter: PageAdapter? = null

    /**
     * The [ViewPager] that will host the section contents.
     */
    private var mViewPager: ViewPager? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val toolbar = findViewById<View>(R.id.toolbar) as Toolbar
        setSupportActionBar(toolbar)

        // Create the adapter that will return a fragment for each of the three
        // primary sections of the activity.
        mSectionsPagerAdapter = PageAdapter(supportFragmentManager, this)

        // Set up the ViewPager with the sections adapter.
        mViewPager = findViewById<ViewPager?>(R.id.container)
        mViewPager!!.adapter = mSectionsPagerAdapter

        val tabLayout = findViewById<View>(R.id.tabs) as TabLayout
        tabLayout.setupWithViewPager(mViewPager)

        // set icons
        tabLayout.getTabAt(0)!!.setIcon(R.drawable.ic_home_white_24dp)
        tabLayout.getTabAt(1)!!.setIcon(R.drawable.ic_dog_white_24dp)
        tabLayout.getTabAt(2)!!.setIcon(R.drawable.ic_small_dog_white_24dp)
        tabLayout.getTabAt(3)!!.setIcon(R.drawable.ic_trained_white_24dp)
        tabLayout.getTabAt(4)!!.setIcon(R.drawable.ic_active_white_24dp)

    }
}

Our MainActivity holds a private field for the ViewPager reference, and in the override of onCreate, we set up our view components by finding them in our associated layout file, then wire up the PageAdapter with our TabLayout. Then we set our icons for each given tab after calling the setupWithViewPager on our TabLayout.

View the Results

We can run our application and view our expected results of our tabs and different list of puppy cards!

Screen Shot 2017-07-05 at 11.14.13 AM

If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.

Advertisements

Xamarin.Tip – PCL Profile Problems

New to Xamarin now that Microsoft is pushing it harder with Visual Studio 2017 and Visual Studio for Mac? Can’t create a new PCL and reference it in your Out of the Box Xamarin.Forms project? This post is for you, and I assure you – you are not alone.

 

The Problem

The core of the problem is this shift within the Microsoft Stack from many different versions of the .NET framework and tools into a “standard” – .NET Standard. However, certain parts of Xamarin aren’t quite there. These are things that worked in Visual Studio 2015, but are now new problems for VS 2017 and VS for Mac, especially if you’re working on a team that uses a mix of these.

There are multiple types of Profiles available for a Portable Class Library. Here’s a quick matrix of the different Profiles and where they compare to .NET Standard versions and supported profiles:

PCL Profile .NET Standard PCL Platforms
Profile7 1.1 .NET Framework 4.5, Windows 8
Profile31 1.0 Windows 8.1, Windows Phone Silverlight 8.1
Profile32 1.2 Windows 8.1, Windows Phone 8.1
Profile44 1.2 .NET Framework 4.5.1, Windows 8.1
Profile49 1.0 .NET Framework 4.5, Windows Phone Silverlight 8
Profile78 1.0 .NET Framework 4.5, Windows 8, Windows Phone Silverlight 8
Profile84 1.0 Windows Phone 8.1, Windows Phone Silverlight 8.1
Profile111 1.1 .NET Framework 4.5, Windows 8, Windows Phone 8.1
Profile151 1.2 .NET Framework 4.5.1, Windows 8.1, Windows Phone 8.1
Profile157 1.0 Windows 8.1, Windows Phone 8.1, Windows Phone Silverlight 8.1
Profile259 1.0 .NET Framework 4.5, Windows 8, Windows Phone 8.1, Windows Phone Silverlight 8

Now we can look at the different .NET Standard versions and their supported platforms:

 

.NET Standard 1.0 1.1 1.2 1.3 1.4 1.5 1.6 2.0
.NET Core 1.0 1.0 1.0 1.0 1.0 1.0 1.0 2.0
.NET Framework (with tooling 1.0) 4.5 4.5 4.5.1 4.6 4.6.1 4.6.2
.NET Framework (with tooling 2.0 preview) 4.5 4.5 4.5.1 4.6 4.6.1 4.6.1 4.6.1 4.6.1
Mono 4.6 4.6 4.6 4.6 4.6 4.6 4.6 vNext
Xamarin.iOS 10.0 10.0 10.0 10.0 10.0 10.0 10.0 vNext
Xamarin.Android 7.0 7.0 7.0 7.0 7.0 7.0 7.0 vNext
Universal Windows Platform 10.0 10.0 10.0 10.0 10.0 vNext vNext vNext
Windows 8.0 8.0 8.1
Windows Phone 8.1 8.1 8.1
Windows Phone Silverlight 8.0

 

Xamarin.Forms is created to support everything from Windows Silverlight 8.0 and up. This means that Xamarin.Forms projects are created using a Profile 259 PCL. This is fine, however, Profile 259 is on it’s way out the door, and therefore can’t be created in Visual Studio 2017! When you create a new PCL in VS 2017, it is created with the latest version of .NET Standard that supports .NET Core, UWP, and Xamarin (as of now this is default to Profile7. However, this is incompatible with Profile 259 and therefore cannot be referenced by your newly created Xamarin.Forms project. There’s no way in the IDE or properties to get it to 259, so if you do still want to support Windows Phone and Windows 8 with your Xamarin Projects in Visual Studio 2017, read below. If you don’t, update your Xamarin.Forms project to remove support for Windows 8 and Windows phone and your profiles will be matching again.

Here’s what the default Xamarin.Forms project targets are:
Screen Shot 2017-07-03 at 11.42.45 AM

And here is what a newly created PCL project targets are with everything selected:

Screen Shot 2017-07-03 at 11.42.58 AM

 

The Solution

We need to get our newly created PCLs to Profile 259 in order to reference them in our Xamarin.Forms project. We can’t do this in the IDE, so we need to dive into the .csproj file itself and make some changes:

NewPCL.csproj

<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import ... />
  <PropertyGroup>
    <MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{4a6a9117-1715-47ea-a6c7-6b0fd5b31bdb}</ProjectGuid>
    <OutputType>Library</OutputType>
    <RootNamespace>NewPCL</RootNamespace>
    <AssemblyName>NewPCL</AssemblyName>
    <DefaultLanguage>en-US</DefaultLanguage>
    <FileAlignment>512</FileAlignment>
    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>

    <!-- THIS IS WHAT NEEDS TO CHANGE -->
    <TargetFrameworkProfile>Profile7</TargetFrameworkProfile>


    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
  </PropertyGroup>
...
</Project>

Take that line of Profile7 and update it to Profile259 so that it looks like this all together:

<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import ... />
  <PropertyGroup>
    <MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{4a6a9117-1715-47ea-a6c7-6b0fd5b31bdb}</ProjectGuid>
    <OutputType>Library</OutputType>
    <RootNamespace>NewPCL</RootNamespace>
    <AssemblyName>NewPCL</AssemblyName>
    <DefaultLanguage>en-US</DefaultLanguage>
    <FileAlignment>512</FileAlignment>
    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>

    <!-- THIS IS WHAT HAS CHANGED -->
    <TargetFrameworkProfile>Profile259</TargetFrameworkProfile>


    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
  </PropertyGroup>
...
</Project>

 
Now you’ll be able to add this project as a reference in your Xamarin.Forms PCL project and continue on.

I know this is pretty annoying to do on large projects that contain many different project files. Take a look at my Onion Architecture project as an example…

This is something that is happening because of this weird in-between state we are at with .NET tooling and the move to .NET Standard. Going forward, Xamarin.Forms will be dropping support for Windows Phone Silverlight which will no longer require Profile259 in order to build our applications in Xamarin.Forms. However, for now, this is the fix for new projects!

Still Broken?

Still having issues with your project structures? Leave a comment and I’ll try to help resolve it.

If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.

Xamarin.Tip – Mvvm Light and Dependency Injection

Inversion of Control and Dependency Injection are some design principles that help make our applications more flexible and scalable. They both help us separate our implementations and make it easy to substitute drastic changes to our implemented data or business logic whether it be for writing unit tests or product improvement.

Xamarin is a platform where IoC and DI fit extremely well. I’ve talked about this concept a few other times in both my blogs and videos about the Onion Architecture in Xamarin as well as how to call Platform Specific code from a Portable Class Library. You can find those posts and videos here:

  1. Onionizing Xamarin Part 6
  2. [VIDEO] Xamarin.Tips: Calling Platform-Specific Code from a PCL (Dependency Injection)

In this post, I want to talk about using DI with Mvvm Light at a VERY basic level.

First, let’s define an interface for a service we might use:

IUserService.cs

public interface IUserService
{
    Task<User> GetCurrentUserAsync();
}

Now let’s create two different implementations. One that will be the service used in the application and the other that will be used for testing.

UserService.cs

public class UserService : IUserService
{
    // makes a call to a web api to get a user
    public async Task<User> GetCurrentUserAsync()
    {
        using (var client = new HttpClient())
        {
            var response = await client.GetAsync("https://mywebapi.mydomain/api/currentuser");
            var content = await response.Content.ReadAsStringAsync();
            return JsonConvert.DeserializeObject<User>(content);
        }
    }
}

TestUserServices.cs

public class TestUserService : IUserService
{
    public Task<User> GetCurrentUserAsync()
    {
        return Task.FromResult(new User { Name = "Test User" });
    }
}

Now we need a ViewModel that will use this service. We define a private readonly IUserService and then inject the implementation that we want in the constructor of the ViewModel.

CurrentUserViewModel.cs

public class CurrentUserViewModel : ViewModelBase
{
    // use the interface as the service and inject the implementation in the constructur
    private readonly IUserService _userService;
    private User _user;

    public User User
    {
        get
        {
            return _user;
        }
        set
        {
            Set(ref _user, value);
        }
    }

    public CurrentUserViewModel(IUserService userService)
    {
        _userService = userService;
    }

    public async Task UpdateUserAsync()
    {
        User = await _userService.GetCurrentUserAsync();
    }
}

Now let’s define an IoCConfig that handles registering dependencies and implementations.

IoCConfig.cs

public class IoCConfig
{
    public IoCConfig()
    {
        // use SimpleIoc from MvvmLight as our locator provider
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
    }

    // register the real implementation
    public void RegisterServices()
    {
        SimpleIoc.Default.Register<IUserService, UserService>();
    }

    // register the test implementation
    public void RegisterTestServices()
    {
        SimpleIoc.Default.Register<IUserService, TestUserService>();
    }

    // register the view model
    public void RegisterViewModels()
    {
        SimpleIoc.Default.Register<CurrentUserViewModel>();
    }
}

Now that we can register our Services as well as our ViewModels, the dependency resolver from SimpleIoc can retrieve an instance of CurrentUserViewModel with whichever version of IUserService is registered depending on whether we call RegisterServices or RegisterTestServices.

Now we can retrieve our instance of the CurrentUserViewModel by calling

var currentUserViewModel = ServiceLocator.Current.GetInstance<CurrentUserViewModel>();

MvvmLight recommends using a ViewModelLocator to get the instance of your ViewModels:

ViewModelLocator.cs

public class ViewModelLocator
{
    private readonly IoCConfig _iocConfig;
    public CurrentUserViewModel CurrentUser
    {
        get
        {
            return ServiceLocator.Current.GetInstance<CurrentUserViewModel>();
        }
    }

    public ViewModelLocator()
    {
        _iocConfig = new IoCConfig();
        _iocConfig.RegisterServices();
        //_iocConfig.RegisterTestServices();
        _iocConfig.RegisterViewModels();
    }

}

It’s recommended to either create your ViewModelLocator at the app start up, or if you’re using Xamarin.Forms, register it as a Resource in your App.xaml

<Application ...     xmlns:locator="clr-namespace:YOUR_LOCATOR_LOCATION">
    <Application.Resources>
        <ResourceDictionary>
            <locator:ViewModelLocator x:Key="Locator"/>
        </ResourceDictionary>
    </Application.Resources>
</Application>

Now in your XAML pages, you can automatically wire up your view model.

MainPage.xaml

<ContentPage ...     BindingContext="{Binding Source={StaticResource Locator}, Path=CurrentUser}"     Title="{Binding User.Name}">
...
</ContentPage>

In order to change to your testing data, you can just switch which call to your IoCConfig is made for registering your dependency without having to make any changes to any of your other layers or UI!

If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.

Xamarin.Tips – MVVM Light Set Expressions Explained

I recently published a post about creating some Visual Studio code snippets for shorcutting the overhead of writing bindable properties and commands with MvvmLight. Xamarin.Tips – Visual Studio Code Templates/Snippets for MVVM Light

This post sparked some people who may or may not have used  Mvvm Light in the past to ask me about how it works underneath, and specifically the Set call made. For example:

private string _myText;

public string MyText
{
    get
    {
        return _myText;
    }
    set
    {
        // This is where the questions are.
        Set(() => MyText, ref _myText, value);
    }
}

I figured I would make another post to dissect this and explain what it is and how it is used!


First off, why are we doing this at all? What does this really do for us?

We use MvvmLight in order to create two-way or one-way bindings to our views whether that is in WPF, UWP, or Xamarin.Forms. The way these bindings are handled is by implementing INotifyPropertyChanged. When we implement INotifyPropertyChanged, we create a public event called PropertyChanged. PropertyChanged takes a custom EventArgs that includes the name of the property that was changed as a string. You would invoke that like this:

PropertyChanged?.Invoke(new PropertyChangedEventArgs("MyText"));

We can then have an event handler attached to this:

myViewModel.PropertyChanged += (sender, args) =>
{
    Console.WriteLine(args.PropertyName); // "MyText"
};

However, platforms such as WPF, UWP, and Xamarin give us the ability to use XAML to create these bindings like this (in Xamarin.Forms):

<Label Text="{Binding MyText}"/>

Setting bindings like this creates event handlers in the background if the BindingContext (or DataContext if you’re in UWP/WPF) implements INotifyPropertyChanged.

So now we can create auto-updating views with our bindings and calling PropertyChanged, but that’s a pain to do for every single property. That’s where libraries like MvvmLight come into play. They help handle a lot of the manual calls and ugly code. So now let’s look at what MvvmLight is really doing under the covers.

First, we need to look at the ViewModelBase class that MvvmLight ships and that contains the Set method we are talking about. ViewModelBase inherits from ObservableObject (another class MvvmLight), and ObservableObject is what is implementing INotifyPropertyChanged! We found it!

So how are ViewModelBase.Set and ObservableObject.Set making their way to calling PropertyChanged?

Let’s dissect the three parameters for the Set method used in the templates I created:

Set(() => MyText, ref _myText, value);
  1. The first is of type Expression<Func>. It is an expression that is returning the property that is calling it? This is where the fun stuff is really happening, so more on that later.
  2. The second is the underlying field that needs to be updated, passed in as a reference type rather than by value.
  3. The third is the new value that it is being set to.

The last two seem to make sense right away: what field are we updating, and what is the value we are setting it to? We need to pass the field in as a ref so that when we update it, it updates in the original model that passed it in rather than simply passing the value of the field into the method.

So what is that Expression?

The only thing left in order to call PropertyChanged is the name of the property being updated, so that must be what the property expression is for. Without decompiling the MvvmLight dlls and looking at the source code, we can infer how we might be able to pull the property name out of that Expression.

First, we need to get the Body of the Expression as a System.Linq.Expression.MemberExpression. The MemberExpression has a Member property which we can then pull property info from. We can cast that Member as a System.Reflection.PropertyInfo, and with that PropertyInfo, we can take the name of the property.

Expression<Func<string>> myTextExpression = () => MyText;
var body = myTextExpression.Body as MemberExpression;
var member = body.Member as PropertyInfo;
var finalPropertyName = member.Name; // we have it!

Then the final step is to finally invoke PropertyChanged with that property name.

I do also want to point out that although I use this particular Set method from MvvmLight, the ObservableObject and ViewModelBase do come with multiple overloads of Set that might work better for your preferred practices. For example, you can call Set without the property expression, and just pass the name of the property in directly. For example:

private string _myText;

public string MyText
{
    get
    {
        return _myText;
    }
    set
    {
        Set("MyText", ref _myText, value); 
    }
}

OR to be even more optimized, you can use nameof to get the name of the property without having to have string-literals floating around in your code:

private string _myText;

public string MyText
{
    get
    {
        return _myText;
    }
    set
    {
        Set(nameof(MyText), ref _myText, value); 
    }
}

Here are all the overloads available to use:

ViewModelBase.cs

protected bool Set<T>(Expression<Func<T>> propertyExpression, ref T field, T newValue, bool broadcast);
protected bool Set<T>(string propertyName, ref T field, T newValue = default(T), bool broadcast = false);
protected bool Set<T>(ref T field, T newValue = default(T), bool broadcast = false, [CallerMemberName] string propertyName = null);

ObservableObject.cs

// THIS IS THE ONE WE WERE USING
protected bool Set<T>(Expression<Func<T>> propertyExpression, ref T field, T newValue);
protected bool Set<T>(string propertyName, ref T field, T newValue);
protected bool Set<T>(ref T field, T newValue, [CallerMemberName] string propertyName = null);

If you happen to have any other questions about how this works, or about breaking down Expressions like we did, feel free to drop a comment on this post, or mention me on Twitter @Suave_Pirate.



And as always:



If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring your developer content? Message me on twitter @Suave_Pirate for details.

Xamarin.Tips – Extending Xamarin Plugins

An Introduction to Plugins

If you’re on my blog, you know I love Xamarin. Writing cross-platform applications and sharing as much code as possible is, in my opinion, the way to go. The Xamarin community has taken an awesome technology, and made it even more awesome by building tons and tons of plugins. These plugins allow us to access platform-specific functionality from shared code, which simply allows us as application developers to write even more code in our portable projects.

I ran into an interesting forum post talking about the structure of plugins made a standard by Xamarin. A lot of use these plugins, but of course, they are not made for everyone! I’ve seen many repositories riddled with issues asking for more and more features in the plugin. This post is going to show some ways to expand on those features with your own code! As well as show techniques to use these plugins with Inversion of Control and Dependency Injection, rather than through the Singleton that the standard ships with.

Suggested Resources Before Starting

It might be a good idea to read up on my blogs and watch my videos about calling platform specific code from a PCL. Check out the YouTube playlist for some different techniques. Specifically looking at the Singleton method and Dependency Injection method.

Resources for Examples

We are going to look at arguably my all time favorite plugin: UserDialogs by Allan Ritchie

If you haven’t used it yet, it’s a cool plugin that allows you to call platform specific pop ups and dialogs including alerts, toasts, prompts, action sheets, confirmation messages, and more.

We are also going to be using MvvmLight (as I tend to do) in order to use SimpleIoc for our Inversion of Control and Dependency Injection.

Let’s first look at using IoC and DI, then look at extending the functionality.

Use Dependency Injection to Call Your Plugins

If we look at Singleton of UserDialogs, we see that it simply changes the Init method based on the platform, and uses that to set the platform-specific implementation of IUserDialogs. The core of the functionality comes from that implementation of IUserDialogs. So rather than going through the Init method of the Singleton, we can instead register the implementation to an IoC container, and inject it into the constructor of our ViewModel or Service that calls it!

Let’s create a ViewModel that takes an IUserDialogs in its constructor:

public class MyViewModel : ViewModelBase
{
    ...
    private readonly IUserDialogs _userDialogs;
    public MyViewModel(IUserDialogs userDialogs)
    {
        _userDialogs = userDialogs;
    }
    ...
 }

Now that our ViewModel has a reference to an IUserDialogs, we can make calls to it from ICommands or methods.

public void ErrorToast(string message)
{
    // show a toast message with a red background
    _userDialogs.Toast(new ToastConfig(message).SetMessageTextColor(System.Drawing.Color.White).SetBackgroundColor(System.Drawing.Color.FromArgb(255, 213, 0, 0)));
}

 

 

Now all we need to do is register both our IUserDialogs platform implementation and our MyViewModelto our IoC container.

In our PCL or SharedLibrary:


...
ServiceLocator.SetLocatorProvider(() =&gt; SimpleIoc.Default);
...
SimpleIoc.Default.Register&lt;MyViewModel&gt;();
...

Then in our Android project:


...

 ActivityLifecycleCallbacks.Register(activity);
var userDialogsImplementation = new UserDialogsImpl(() =&gt; ActivityLifecycleCallbacks.CurrentTopActivity);
SimpleIoc.Default.Register&lt;IUserDialogs&gt;(() =&gt; userDialogsImplementation);
...

And in iOS:

...
// note iOS doesn't require registering lifecycle callbacks like iOS does.
SimpleIoc.Default.Register&lt;IUserDialogs, UserDialogsImpl();
...

Now when we create our MyViewModel, we don’t do it through calling new MyViewModel(), we will call to get the instance from the ServiceLocator. For example, we can set the BindingContext of a Page:

 

...
public MyMainPage()
{
    BindingContext = ServiceLocator.Current.GetInstance&lt;MyViewModel&gt;();
}
...

That’s all we need to do! As long as we make those Register calls for our MyViewModel and IUserDialogs before the call to the MyMainPage constructor, everything will be wired up and Injected.

Now that we have our application using Dependency Injection instead of the Singleton, it makes it even easier to override and extend the functionality of the plugin.

Changing Features and Functionality

There are only two things we need to change to our implementation from above.

  1. Create a new platform implementation of IUserDialogs that inherits from the UserDialogsImpl.
  2. Change the IoC Registration to use our new implementation.

Let’s create a new class called MyUserDialogsImpl that will inherit from UserDialogsImpl. In this class, we will override the Alert method and do something like change the Tint color on iOS:


public class MyUserDialogsImpl : UserDialogsImpl
{
    ...
    public override IDisposable Alert(AlertConfig config)
    {
        return this.Present(() =&gt;
        {
             var alert = UIAlertController.Create(config.Title ?? String.Empty, config.Message, UIAlertControllerStyle.Alert);

            // custom piece:
            alert.View.TintColor = UIColor.Red;

             alert.AddAction(UIAlertAction.Create(config.OkText, UIAlertActionStyle.Default, x =&amp;amp;amp;amp;amp;gt; config.OnAction?.Invoke()));
             return alert;
         });
     }

 ...
}

Now where we registered the IUserDialogs before, we just substitute our new implementation!

 

...
// note iOS doesn't require registering lifecycle callbacks like iOS does.
SimpleIoc.Default.Register&lt;IUserDialogs, MyUserDialogsImpl&gt;();
...

So now our IoC set up will automatically set up our new implementation, so when we call the Alert method, it will show the Tint color as Red.

Adding New Features to Plugins

Similarly to how we changed functionality, we can add completely new functionality in just a few steps:

  1. Create a new Interface that inherits IUserDialogs in our shared code.
  2. Add a new method to that interface
  3. Change our new implementation to also implement that new interface
  4. Change our IoC Registration to register our implementation as our new interface instead of IUserDialogs
  5. Change our injected dependency in our MyViewModel to our new interface

In our shared code, let’s create an interface called ICustomDialogs and add a method to its definition:


public interface ICustomDialogs : IUserDialogs
{
    void SayHello();
}

 

Now, let’s update our MyUserDialogsImpl to implement our new interface:


public class MyUserDialogsImpl : UserDialogsImpl, ICustomDialogs
{
    public void SayHello()
    {
        this.Alert(&quot;Hello&quot;, &quot;World&quot;);
    }
}

Next, we need to update our IoC Register call:

 

 


...
SimpleIoc.Default.Register&lt;ICustomDialogs, MyUserDialogsImpl&gt;();
...

Lastly, let’s change our MyViewModel to use our new interface:

public class MyViewModel : ViewModelBase 
{ 
    ...
    private readonly ICustomDialogs _userDialogs; 
    public MyViewModel(ICustomDialogs userDialogs)
    {
        _userDialogs = userDialogs; 
    } 
    ...
}

Now we can call our SayHello method from our ViewModel too!

Recap

  1. Xamarin Plugins are awesome
  2. You don’t have to use Plugin Singletons!
  3. You can use dependency injection to inject your plugin implementations
  4. You can override methods in your platform specific implementations of your plugins
  5. You can create new functionality through another interface and updated injections!

Xamarin.Tips – Super Simple Sqlite

Thinking about locally storing data and entity structures can be intimidating. You might have a complex data structure in your backend server structure and are trying to match that type of data in your mobile apps. Perhaps you’ve just never done it before and need a solution quickly. You might be over thinking it!

Let’s break it down into some straightforward steps.

  1. Create a Xamarin PCL or Shared project. It doesn’t matter if it’s Xamarin.Forms or native.
  2. Install this nuget package in your PCL or Shared project: https://www.nuget.org/packages/sqlite-net-pcl/
  3. Install the same nuget package in your Android, iOS, UWP, and any other project.
  4. Create your model in your PCL or Shared project. In this case, we will use a basic example model:
    public class Profile
    {
        public string Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Handle { get; set; }
        public DateTime CreatedDate { get; set; }
    }
    
  5. Create a DbContext class in your PCL or Shared project:
    public class DbContext
    {
        public static string LocalFilePath; // Set this before creating from platform project
        public SQLiteAsyncConnection Database { get; }
        /// <summary>
        /// Initialized a new DbContext
        /// </summary>
        public DbContext()
        {
            Database = new SQLiteAsyncConnection(LocalFilePath + "localdb.db3");
        }
    
        /// <summary>
        /// Creates a table for a given type in sql lite
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public async Task<CreateTablesResult> CreateTableAsync<T>() where T : new()
        {
        return await Database.CreateTableAsync<T>();
        }
    
        /// <summary>
        /// Gets a table by it's type from the db.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public AsyncTableQuery<T> Set<T>() where T : new()
        {
            return Database.Table<T>();
        }
    }
    
  6. Create a GenericRepository Class:
    public class GenericSqliteRepository<T> : IGenericRepository<T> where T : new()
    {
        protected readonly DbContext _context;
        public GenericSqliteRepository(DbContext context)
        {
            _context = context;
        }
        public virtual async Task InitializeAsync()
        {
            await _context.CreateTableAsync<T>();
        }
        public virtual async Task AddAsync(T entity)
        {
            await _context.Database.InsertOrReplaceAsync(entity);
        }
        public virtual async Task AddRangeAsync(IEnumerable<T> entities)
        {
            await _context.Database.InsertAllAsync(entities);
        }
    
        public virtual async Task<T> FindAsync(Expression<Func<T, bool>> predicate)
        {
            return await _context.Set<T>().Where(predicate).FirstOrDefaultAsync();
        }
    
        public virtual async Task<IEnumerable<T>> GetAsync(Expression<Func<T, bool>> predicate)
        {
            return await _context.Set<T>().Where(predicate).ToListAsync();
        }
    
        public virtual async Task<IEnumerable<T>> GetAsync(int skip, int take)
        {
            return await _context.Set<T>().Skip(skip).Take(take).ToListAsync();
        }
    
        public virtual async Task<IEnumerable<T>> GetAsync(Expression<Func<T, bool>> predicate, int skip, int take)
        {
            return await _context.Set<T>().Where(predicate).Skip(skip).Take(take).ToListAsync();
        }
    
        public virtual async Task RemoveAsync(T entity)
        {
            await _context.Database.DeleteAsync(entity);
        }
    
        public virtual async Task UpdateAsync(T entity)
        {
            await _context.Database.UpdateAsync(entity);
        }
    }
    
  7. Create a ProfileRepository Class:
    public class ProfileRepository : GenericSqliteRepository<Post>
    {
        public ProfileRepository(DbContext context) : base(context)
        {
        }
    }
    
  8. Set your file path in your platform code:
    1. Android
      DbContext.LocalFilePath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
      
    2. iOS
      var docFolder = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
      string libFolder = Path.Combine(docFolder, "..", "Library", "Databases");
      
      if (!Directory.Exists(libFolder))
      {
          Directory.CreateDirectory(libFolder);
      }
      DbContext.LocalFilePath = libFolder;
      
  9. Use your repository in your shared code or platform code or wherever you want.
    var repo = new ProfileRepository(new DbContext());
    await repo.InitializeAsync();
    ...
    await repo.AddAsync(new Profile {...});
    ...
    var profiles = await repo.GetAsync(0, 10);
    ...
    var profile = await repo.FindAsync(p => p.Id == "foo");
    ...
    
  10. Start storing your things!

This is obviously a simple situation that doesn’t cover all needs, but it’s a place to start for complex data models. Build repositories for each of your types. Control your queries that are very specific in those model-specific repositories.

Look out for a follow up post about some patterns and tips to use for complex and large data sets!

Xamarin.Tips – Calling Platform-Specific Code from a Portable Class Library – Xamarin.Forms DependencyService

For those who just want code: https://github.com/SuavePirate/Xamarin.HockeyApp.Portable

For those who just want the video: [VIDEO] Xamarin.Tips: Calling Platform-Specific Code from a PCL (Xamarin.Forms DependencyService)

As we develop our applications to be cross-platform, we try to share as much code between different platforms as possible. Many times, though, we have a need to call platform-specific code from that shared code; whether it be something such as playing a sound file, handling hardware readings, or using a third-party SDK that isn’t abstracted to be shareable.

In these examples, we will look at implementing parts of the HockeyApp SDK that are specific to the platform you are running against such as showing the Feedback control to ask your users to report bugs or give feedback.

There are a few ways to accomplish this, but in this post, we will look at using the Xamarin.Forms DependencyService.

The Xamarin.Forms DependencyService allows us to register implementations in our platform code as the implementation of an interface defined in our shared code. We can then use the Get() method from the DependencyService to get a reference to the platform code in our shared code.

To start, in our shared code, we will create an interface that will be implemented on our platforms:

public interface IHockeyService
{
    void Init();
    void GetFeedback();
}

 

Now in our platform projects, we will implement our IHockeyService. The important thing to note is the assembly level attribute tag we put over our namespace. This tag is what registers our implementation to the Dependency Service!

iOS:

[assembly: Xamarin.Forms.Dependency(typeof(HockeyService))]
namcespace YOUR_NAMESPACE
{
    public class HockeyService : IHockeyService
    {
        public HockeyService()
        {
        }

        public void GetFeedback()
        {
            BITHockeyManager.SharedHockeyManager.FeedbackManager.ShowFeedbackListView();
        }

        public void Init()
        {
            var manager = BITHockeyManager.SharedHockeyManager;
            manager.Configure("HOCKEY_APP_ID");
            manager.StartManager();
        }
    }
}

Android:

[assembly: Xamarin.Forms.Dependency(typeof(HockeyService))]</pre>
namcespace YOUR_NAMESPACE
{
    public class HockeyService : IHockeyService
    {
        private const string HOCKEYAPP_KEY = "HOCKEY_APP_ID";
        private readonly Android.App.Application _androidApp;
        private readonly Activity _context;

        public HockeyAppService(Activity context, Android.App.Application androidApp)
        {
            _context = context;
            _androidApp = androidApp;
        }

        public void GetFeedback()
        {
            FeedbackManager.ShowFeedbackActivity(_context.ApplicationContext);
        }

        public void Initialize()
        {
            CrashManager.Register(_context, HOCKEYAPP_KEY);
            MetricsManager.Register(_androidApp, HOCKEYAPP_KEY);
            UpdateManager.Register(_context, HOCKEYAPP_KEY);
            FeedbackManager.Register(_context, HOCKEYAPP_KEY);
        }
    }
}

Now we need to initialize the HockeyApp manager from our shared code.

App.xaml.cs

public App ()
{
    DependenyService.Get<IHockeyService>().Init();
}

Now that our service is registered to the DependencyService, we can make calls to it from our Shared code. In this example, we will add a button to a Xamarin.Forms page with a click handler that calls the service:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="YourNamespace.MainPage">

    <Button Text="Get feedback with the dependency service!"
            VerticalOptions="Center"
            HorizontalOptions="Center"
            Clicked="Feedback_Clicked"/>

</ContentPage>

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
    }

    private void Feedback_Clicked(object sender, EventArgs e)
    {
        DependencyService.Get<IHockeyService>().GetFeedback();
    }
}

Now our results will show that our shared code call to the service successfully shows the HockeyApp UI

simulator-screen-shot-feb-15-2017-1-47-26-pm