Evolution of the NuGet PackageReference

NuGet is probably the best thing that happened to .NET dependencies. Before this great time, we all had to copy or worse, commit a bunch of assemblies into source control – just so we could build our projects. And for library developers… well, we had to find someone to host our libraries.

When NuGet was born, we could just throw our libraries up on nuget.org and be done with it. We could tweet about it and then anyone could open the package manager and click install. The repository stayed binary-free and the library started growing in users. Great for everyone.

Both NuGet and MSBuild have evolved much over time, and there have been a few different incarnations of the simple, but complex, feature of including a NuGet package into the project file. It took a few tries, but we are at the best so far with PackageReference. But, before we get there, let us recap some of the past ideas…

packages.config

There was a downside to the first NuGet: it scratched around in your .csproj and added a few elements that sometimes got mixed up. Let’s take a simple project, and add SkiaSharp:

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  ...
  <ItemGroup>
    <Reference Include="SkiaSharp">
      <HintPath>..\packages\SkiaSharp.1.58.1\lib\net45\SkiaSharp.dll</HintPath>
    </Reference>
  </ItemGroup>
  ...
  <ItemGroup>
    <None Include="packages.config" />
  </ItemGroup>
  ...
  <Import Project="..\packages\SkiaSharp.1.58.1\build\net45\SkiaSharp.targets" Condition="Exists('..\packages\SkiaSharp.1.58.1\build\net45\SkiaSharp.targets')" />
  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
    <PropertyGroup>
      <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
    </PropertyGroup>
    <Error Condition="!Exists('..\packages\SkiaSharp.1.58.1\build\net45\SkiaSharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\SkiaSharp.1.58.1\build\net45\SkiaSharp.targets'))" />
  </Target>
</Project>

Our beautiful project file just got a bit mutilated… Still, it is not that bad, right? Well, what happens if you use a few packages? You get a project file that has quite a few elements that basically pull in a bunch of assemblies and add a few targets – there is just clutter.

Although this is all correct MSBuild file, the packages are really managed by that packages.config file. The IDE and NuGet use that file to track the installed packages and also to update the project file with the assembly references and target imports.

You can read more about the packages.config file here.

project.json

Along came a spider (named .NET Core) and sat down besIDE her…

The guys working on .NET Core also had had enough of this, (they may have gone a bit too far and removed all XML) so they came up with project.json. Although they threw the .csproj right out of the window, they had a cool idea when it came to NuGet packages: don’t touch the project file.

Initially, project.json was just for ASP.NET Core apps, but they also used it for (and still do) UWP apps. Then, they decided to let other project types use it. If we were to install the SkiaSharp package into a project.json file, we would end up with something like this:

{
  "dependencies": {
    "SkiaSharp": "1.58.1"
  },
  "frameworks": {
    "net46": { }
  },
  "runtimes": {
    "win": { }
  }
}

This WAS way neater than the big, clunky .csproj, and – best of all – NuGet managed itself. No need for assembly references and importing .targets. Also, because NuGet never touched the .csproj, it could never get it wrong.

The downside to project.json was simply the fact that it was no longer MSBuild. There were other project types, such as .xproj that would pull in the project.json and then make it work with MSBuild, but now we have even more files and overhead. The problem of less was undone by the new file type.

You can read more about the project.json file here.

PackageReference

So, the experts got together and decided to come up with a plan – a format to rule them all. They took the idea that NuGet needs to be MSBuild and that it must not touch what it shouldn’t. It needs to be minimal, but still powerful.

This is what they came up with:

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  ...
  <ItemGroup>
    <PackageReference Include="SkiaSharp" Version="1.58.1" />
  </ItemGroup>
  ...
</Project>

No, your browser is not still loading. That simple, single line does it all. There is no additional packages.config or project.json file. That goes directly in the .csproj like any .NET framework reference (such as when including System.IO.Compression).

I could write a big puff piece about how awesome this is, but the whole point is to not have that puff. I really love this new format, and I hope that you will too. I have tested this with many projects, including Xamarin projects. It all works, and it should – it is part of MSBuild, and Xamarin uses MSBuild. This is one of the cool features about having a MSBuild-based project: if MSBuild supports it, then so does your project.

You can read more about the PackageReference format here. And, there is some more information about using PackageReference in any project type here.

Requirements

Using this new PackageReference format makes life so much easier, but there are some things that you will need before you switch over all those projects:

  • MSBuild v15
  • NuGet v4.x

If you want to use an IDE, the best still are:

  • Visual Studio 2017
  • Visual Studio for Mac v7.1

The current set of requirements is just that you need to be using MSBuild v15 (comes with Visual Studio) and NuGet v4.x (also comes with Visual Studio). If you need the NuGet command line tool, you can get it here.

By default, Visual Studio will use the packages.json format, but you can change this in the options. Navigate to “Tools” > “Options…”, then “NuGet Package Manager” > “General”:

NuGet Package Manager

See more information about using PackageReference in any project type here.

Limitations

Right now this magic works on Windows and macOS without anything special. Linux is a bit different… As it has a case-sensitive file system, and NuGet is a little inconsiderate: it downloads the packages as lowercase, but then tries to include the real case.

If you look at the ~/.nuget/packages directory, you will see a skiasharp directory, but when you try and compile, you will get this error:

error : The package SkiaSharp with version 1.58.1 could not be found in /home/matthew/.nuget/packages/. Run a NuGet package restore to download the package.

Exciting stuff! But no worries, until NuGet/MSBuild fixes this, we can just tell Mono to ignore case sensitivity using the MONO_IOMAP environment variable:

> export MONO_IOMAP=all
> msbuild

Or:

> MONO_IOMAP=all msbuild

That was mostly painless. Still, we can set that environment variable per build and not affect any other apps. And, this is just a tiny bit of “work” so that we can get really awesome, clean .csproj files.

So, is there anything stopping you from using the PackageReference in your projects? No! Transition Now!

Multi-Select ListView

I was just hanging around in the IDE this week and I had a chat with ListView. He was a very nice guy, but he was complaining about the fact that for some reason he could only ever select one item at a time…

I think of myself as a somewhat decent coder, and I decided to solve this problem – at least some part of it.

The easiest, and quickest, way to add multi-select capabilities to a ListView requires two steps: the “selectable” item and the “select” action.

The Selectable Item

I started with the model:

public class SelectableItem
{
    public object Data { get; set; }
    public bool IsSelected { get; set; }
}

But, since we are doing data binding, I created a bindable object that has several bindable properties:

public class SelectableItem : BindableObject
{
    public static readonly BindableProperty DataProperty =
        BindableProperty.Create(
            nameof(Data),
            typeof(object),
            typeof(SelectableItem),
            (object)null);

    public static readonly BindableProperty IsSelectedProperty =
        BindableProperty.Create(
            nameof(IsSelected),
            typeof(bool),
            typeof(SelectableItem),
            false);

    public SelectableItem(object data)
    {
        Data = data;
        IsSelected = false;
    }

    public SelectableItem(object data, bool isSelected)
    {
        Data = data;
        IsSelected = isSelected;
    }

    public object Data
    {
        get { return (object)GetValue(DataProperty); }
        set { SetValue(DataProperty, value); }
    }

    public bool IsSelected
    {
        get { return (bool)GetValue(IsSelectedProperty); }
        set { SetValue(IsSelectedProperty, value); }
    }
}

You may have noticed that I didn’t create a generic type. This is because later on we are going to want to get the value of the IsSelected property from the ItemSelected event handler, and we won’t know what the type is. However, we can create a generic type that inherits from this base type:

public class SelectableItem<T> : SelectableItem
{
    public SelectableItem(T data)
        : base(data)
    {
    }

    public SelectableItem(T data, bool isSelected)
        : base(data, isSelected)
    {
    }

    // this is safe as we are just returning the base value
    public new T Data
    {
        get { return (T)base.Data; }
        set { base.Data = value; }
    }
}

We now have a nice generic type for the developer (us) and a non-generic type for the event (the machine).

The Selectable ListView

The next step is to hook up the ListView with the selectable items. So, we will need a data field on the view model or the Page – depending on how you work (note the generic SelectableItem):

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

        Items = new ObservableCollection<SelectableItem<string>>();

        BindingContext = this;
    }

    public ObservableCollection<SelectableItem<string>> Items { get; }
}

And, we need a list item that has a “checked” state (here it is just a red block):

<ListView ItemsSource="{Binding Items}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <StackLayout Orientation="Horizontal">
                    <!-- the "check" mark -->
                    <BoxView IsVisible="{Binding IsSelected}" 
                             WidthRequest="12" HeightRequest="12"
                             Color="Red" />
                    <!-- the text/data -->
                    <Label Text="{Binding Data}" />
                </StackLayout>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

We should now have a list of items that can show either a selected or unselected state. To handle when an item is selected by the user, we just need an event on the list:

<ListView ... ItemSelected="OnItemSelected">
    ...
</ListView>

And then we write the code to toggle the selection (note the non-generic SelectableItem):

private void OnItemSelected(object sender, SelectedItemChangedEventArgs e)
{
    var item = e.SelectedItem as SelectableItem;
    if (item != null)
    {
        // toggle the selection property
        item.IsSelected = !item.IsSelected;
    }

    // deselect the item
    ((ListView)sender).SelectedItem = null;
}

This is all we need, and we will have a ListView that that can support multiple items being selected.

Improvements

We could call it a day, but we are not going to. The day has just started, and we are thinking that we might want to use this in multiple places. We can just copy the logic – mainly the event and cell view, but there are better ways (and we don’t like duplicate code).

Attached Property

The first thing that we will look at is if we can magically do the event hookup with a single property instead of the event:

<ListView ... local:MultiSelectListView.IsMultiSelect="True">
    ...
</ListView>

That looks nicer than the event, and we have a couple of benefits: no code in the page, the event code is written once and the property is bindable.

What we are doing here is using an attached property to “inject” a bindable property into an existing view type:

public static class MultiSelectListView
{
    public static readonly BindableProperty IsMultiSelectProperty =
        BindableProperty.CreateAttached(
            "IsMultiSelect",
            typeof(bool),
            typeof(ListView),
            false,
            propertyChanged: OnIsMultiSelectChanged);

    public static bool GetIsMultiSelect(BindableObject view)
        => (bool)view.GetValue(IsMultiSelectProperty);

    public static void SetIsMultiSelect(BindableObject view, bool value)
        => view.SetValue(IsMultiSelectProperty, value);

    private static void OnIsMultiSelectChanged(
        BindableObject bindable, object oldValue, object newValue)
    {
        var listView = bindable as ListView;
        if (listView != null)
        {
            // always remove event
            listView.ItemSelected -= OnItemSelected;

            // add the event if true
            if (true.Equals(newValue))
            {
                listView.ItemSelected += OnItemSelected;
            }
        }
    }

    private static void OnItemSelected(
        object sender, SelectedItemChangedEventArgs e)
    {
        var item = e.SelectedItem as SelectableItem;
        if (item != null)
        {
            // toggle the selection property
            item.IsSelected = !item.IsSelected;
        }

        // deselect the item
        ((ListView)sender).SelectedItem = null;
    }
}

We now have a super easy way to turn any list into a multi-select list with a single property.

The ItemsSource

Another area we can improve is the ItemsSource collection. Right now we have quite a long type with two generic types:

public ObservableCollection<SelectableItem<string>> Items { get; }

We can not only make this shorter, but more convenient by creating a new type that derives from ObservableCollection. And, now that we have a new type, we can add additional methods so that we don’t even have to deal with the SelectableItem type at all:

public class SelectableObservableCollection<T> : ObservableCollection<SelectableItem<T>>
{
    ...

    // a constructor overload
    public SelectableObservableCollection(IEnumerable<T> collection)
        : base(collection.Select(c => new SelectableItem<T>(c)))
    {
    }

    ...

    // a convenience property
    public IEnumerable<T> SelectedItems
        => this.Where(i => i.IsSelected).Select(i => i.Data);

    ...

    // a method overload
    public void Add(T item)
    {
        Add(new SelectableItem<T>(item));
    }
}

When we use this new type, we can do some cool things:

// a nice type
public SelectableObservableCollection<string> Items { get; }

// cool methods and properties
private void OnDoSomething()
{
    Debug.WriteLine("You have selected:");

    // use a property
    foreach (var selected in Items.SelectedItems)
    {
        Debug.WriteLine($" - {selected.Data}");
    }

    // use a method
    Items.Add("A New String");
}

The Cell

Finally, as you may have a really cool check mark for selected items (unlike our red block now), we will want to be able to create a custom cell type that will allow us to just specify the item contents, and automatically handle the check mark:

<ListView ItemsSource="{Binding Items}"
          local:MultiSelectListView.IsMultiSelect="True">
    <ListView.ItemTemplate>
        <DataTemplate>
            <local:SelectableViewCell>
                <Label Text="{Binding}" />
            </local:SelectableViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

This requires a new Cell type:

[ContentProperty(nameof(DataView))]
public class SelectableViewCell : ViewCell
{
    public SelectableViewCell();

    public View CheckView { get; set; }

    public View DataView { get; set; }
}

I have left the implementation of this cell to your imagination… just kidding, I have it all in my my repository. You can find all this code, a sample app and more there too:

I hope you enjoyed this short(ish) post and are able to make your list views handle the selection of multiple items.

Embedding Xamarin.Forms in Native Apps

Xamarin.Forms is really cool! It allows you to almost write your app once and then compile for many platforms. With Xamarin.Forms, you can quickly produce multiple apps, but, you can also take advantage of some awesome features – such as cross-platform UIs in XAML, data binding, sharing code and much more.

Xamarin.iOS, Xamarin.Android and UWP are also fantastic! You can get 100% of the platform APIs and you can produce apps that are super fast and polished.

Most of the time you have to choose between one or the other. Sure, you can do custom renderers or effects in Xamarin.Forms to get more platform API access. And sure, you can use frameworks that help you share code with native Xamarin and Windows apps. Before today, you had one of two choices:

  • Xamarin.Forms for 100% shared code and UI
  • Xamarin/Windows Native for polished, platform-specific APIs and UIs

But… why not have both? Recently Xamarin/Microsoft shared on the blog that Xamarin.Forms can be embedded into native apps. This means that you can take your existing (or new) native app and just drop in a Xamarin.Forms page without doing anything special. You lose nothing, and gain a whole lot more. You can still use XAML, data binding, converters, effects and everything else that comes with Xamarin.Forms – but now from within you native app code and UI.

I have a nice sample app that you can pull from GitHub. Be sure to check it out and let me know what you think of this new functionality. I will try and keep that repository up to date with any new developments.

Xamarin.Forms embedded in native apps

Getting the Bits

To embed Xamarin.Forms into your native app, you just need to install a preview NuGet from the Xamarin.Forms pre-release feed:

https://www.myget.org/F/xamarinforms-dev/api/v3/index.json

Then, you want to install the 3.0.0.100-embeddingpreview NuGet into any Xamarin.Forms projects as well as into the native app projects.

That is it! Now you should be able to create your shared page.

If you have any questions or comments you can do this using the Xamarin discussion (Preview: Xamarin.Forms Embedding) on the forums.

It is important to note that this is a pre-release and functionality may change with subsequent releases.

Creating Shared Pages

Let’s take an example of an existing app that you want to add the ability to register and/or login to save user preferences on some cloud service – such as Azure. Your app is out and in the wild, users are loving it, and, you have just received feedback that they want to login across devices and keep their preferences.

What do you do? Well you could create a few screens for each platform and then share some code. But, as all the login screens are going to look the same and work the same, why not do everything in shared XAML?

So, the first thing we can do is to either create a shared project, a .NET Standard library or even a PCL. We then just need to install the pre-release Xamarin.Forms NuGet. Finally, we can go ahead an add a new XAML page. Just right-click and do “Add” > “New Item…” > “Content Page (XAML)” and then you have a new page.

In this page below, I am using data binding, converters, resource dictionaries and good old XAML markup:

<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:app="clr-namespace:EmbeddedFormsDemo.Converters"
             x:Class="EmbeddedFormsDemo.Views.LoginPage">
    <ContentPage.Resources>
        <ResourceDictionary>
            <app:NegateConverter x:Key="Negate" />
            <app:NullInvisibilityConverter x:Key="NullInvisibility" />
        </ResourceDictionary>
    </ContentPage.Resources>
    <ScrollView>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>
            <StackLayout Spacing="12" Grid.Row="1">
                <StackLayout.Padding>
                    <OnPlatform x:TypeArguments="Thickness" 
                                Android="24" iOS="24" WinPhone="0" />
                </StackLayout.Padding>
                <Label Text="Enter any username/password:"
                       HorizontalTextAlignment="Center"
                       FontSize="12" />
                <Entry Keyboard="Email" 
                       Placeholder="username or email"
                       Text="{Binding UserName}" 
                       HorizontalTextAlignment="Center"
                       IsEnabled="{Binding IsBusy, Converter={StaticResource Negate}}" />
                <Entry IsPassword="True" 
                       Placeholder="password" 
                       Text="{Binding Password}" 
                       HorizontalTextAlignment="Center"
                       IsEnabled="{Binding IsBusy, Converter={StaticResource Negate}}" />
                <Button Text="Log In" 
                        Command="{Binding LoginCommand}"
                        IsEnabled="{Binding IsBusy, Converter={StaticResource Negate}}" />
                <Label Text="{Binding ErrorMessage}" 
                       HorizontalTextAlignment="Center"
                       FontSize="12"
                       TextColor="Red" 
                       IsVisible="{Binding ErrorMessage, Converter={StaticResource NullInvisibility}}" />
                <ActivityIndicator IsRunning="{Binding IsBusy}" 
                                   IsVisible="{Binding IsBusy}" />
            </StackLayout>
        </Grid>
    </ScrollView>
</ContentPage>

Then, in our code-behind, we can write out code to work with the UI. Here we have made use of several features such as binding, commands, messaging and async/await:

[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class LoginPage : ContentPage
{
    public const string LoginMessage = "login";

    private readonly JsonPlaceholderApi api;
    private string errorMessage;

    public LoginPage()
    {
        InitializeComponent();

        // initialize our fake services
        api = new JsonPlaceholderApi();

        // set up the data binding
        LoginCommand = new Command(OnLogin);
        BindingContext = this;
    }

    private async void OnLogin()
    {
        IsBusy = true;

        // reset errors
        ErrorMessage = "";
        // try logging in with our fake services
        var user = await api.LoginAsync(UserName, Password);
        if (user == null) {
            // there was an error
            ErrorMessage = "There was a problem logging in.";
        } else {
            // let the app know we are finished
            MessagingCenter.Send(user, LoginMessage);
        }

        IsBusy = false;
    }

    public string ErrorMessage
    {
        get { return errorMessage; }
        set { errorMessage = value; OnPropertyChanged(); }
    }

    // we don't want to save this as the user types
    public string UserName { get; set; }

    // we don't want to save this at all
    public string Password { get; set; }

    // the login button uses this
    public ICommand LoginCommand { get; }
}

That is basically all we need to do in order to create our UI. The JsonPlaceholderApi type just makes use of http://jsonplaceholder.typicode.com to get some random data, the User type is just a simple POCO object and the converters are basic IValueConverter implementations.

Displaying Shared Pages in Native Apps

Once we have created our shared Xamarin.Forms page, we can just instantiate out Xamarin.Forms page and then ask for the native version.

On Android, the CreateFragment extension method will return a native Android Fragment, which we can then use as we would any other fragment. On iOS, we use the CreateViewController extension method and we will get out a native UIViewController that, again, we can use as we would any other view controller. And finally, on Windows, we use the CreateFrameworkElement extension method to get out a native FrameworkElement that we can also uses as any other element.

There are two steps to obtaining this native container, first we make sure Xamarin.forms is initialized:

// Android
Xamarin.Forms.Forms.Init(this, null);

// iOS
Xamarin.Forms.Forms.Init();

// Windows
// the `e` from `Application.OnLaunched(LaunchActivatedEventArgs e)`
Xamarin.Forms.Forms.Init(e);

Once that is done, we can then get the native page:

// create the Xamarin.Forms page for all platforms
var formsPage = new MyFormsPage();

// Android - get the native Fragment
var nativeFragment = formsPage.CreateFragment(this);

// iOS - get the native UIViewController
var nativeController = formsPage.CreateViewController();

// Windows - get the native FrameworkElement
var nativeElement = formsPage.CreateFrameworkElement();

Now that we have the native view, we can just go ahead and use it as if it was created using the traditional mechanisms.

Xamarin.Android and Xamarin.Forms

When using Xamarin.Forms with an Android app, we are going to need to handle the native Fragment that represents the page. To this end, our Android app is using a native .axml layout with a FrameLayout that will hold all our fragments:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <!-- the other bits of UI -->
    <FrameLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:id="@+id/frameLayout" />
    <!-- some more UI -->
</RelativeLayout>

Then, in our main activity code, we load this UI as normal and everything works as it usually does. When we want to show our new XAML page at some point, all we need to do is to just make sure Xamarin.Forms is initialized and then instantiate the page before navigating to it:

using Xamarin.Forms.Platform.Android;

public void DisplayLogin()
{
    if (!Xamarin.Forms.Forms.IsInitialized)
    {
        // initialize Xamarin.Forms before we use it
        Xamarin.Forms.Forms.Init(this, null);

        // we want to listen to the messaging center
        Xamarin.Forms.MessagingCenter.Subscribe(this, LoginPage.LoginMessage, (User user) =>
        {
            // update the app
            CurrentUser = user;

            // go back to the main page
            FragmentManager.PopBackStack();
        });
    }

    // create the login page (Xamarin.Forms ContentPage)
    var loginPage = new LoginPage();

    // get hold of the native Android fragment that represents the Xamarin.Forms page
    var loginFragment = loginPage.CreateFragment(this);

    // show the login screen (native Xamarin.Android)
    FragmentManager
        .BeginTransaction()
        .AddToBackStack(null)
        .Replace(Resource.Id.frameLayout, loginFragment)
        .Commit();
}

Xamarin.iOS and Xamarin.Forms

If we want to use Xamarin.Forms in our iOS app, we will be showing a new UIViewController. We first need to make sure that Xamarin.Forms is initialized and then we can just go ahead and create the desired page. We then get the native view controller that can be presented using all the existing means:

using Xamarin.Forms;

partial void OnLoginClicked(UIButton sender)
{
    if (!Xamarin.Forms.Forms.IsInitialized)
    {
        // initialize Xamarin.Forms before we use it
        Xamarin.Forms.Forms.Init();

        // we want to listen to the messaging center
        Xamarin.Forms.MessagingCenter.Subscribe(this, LoginPage.LoginMessage, (User user) =>
        {
            // update the app
            User = user;

            // go back to the main page
            NavigationController.PopViewController(true);
        });
    }

    // create the login page (Xamarin.Forms ContentPage)
    var loginPage = new LoginPage();

    // show the login screen
    var viewController = loginPage.CreateViewController();
    NavigationController.PushViewController(viewController, true);
}

Windows UWP and Xamarin.Forms

When we want to show a Xamarin.Forms page within our native UWP app, we will work with a FrameworkElement. Like with all the other platforms, we have to make sure that Xamarin.Forms is initialized and then just create the page. Once we have obtained the native element, we can just place it anywhere we need it to be. In this example, I am placing my view in a Flyout as the it is being opened:

using Xamarin.Forms;

private void OnLoginFlyoutOpening(object sender, object e)
{
    var flyout = sender as Flyout;

    if (!Xamarin.Forms.Forms.IsInitialized)
    {
        // initialize Xamarin.Forms before we use it
        Xamarin.Forms.Forms.Init(App.LastLaunchEventArgs);

        // we want to listen to the messaging center
        Xamarin.Forms.MessagingCenter.Subscribe(this, LoginPage.LoginMessage, (User user) =>
        {
            // update the app
            User = user;
            // show some message for some random reason
            WelcomeText = $"Welcome back {user.Name}!";

            // hide the login screen
            flyout.Hide();
        });
    }

    // create the login page (Xamarin.Forms ContentPage)
    var loginPage = new LoginPage();

    // set the native dialog to contain the shared login
    var loginElement = loginPage.CreateFrameworkElement();
    flyout.Content = new Frame
    {
        Content = loginElement,
        Width = 300,
        Height = 200
    };
}

Summary

In this fairly long post, we looked at how to quickly embed a Xamarin.Forms page into an existing native app. The process is easy and painless, and will only get better.

You can download the full code from my GitHub repository and try it out for yourself. And maybe have a look at your app and see if some of those screens that are exactly the same could use Xamarin.Forms.

You can also check out some links:

Some other people also have blogs:

And, then there is code: