Introduction
The point of this walkthrough is get you up and running with a quick Xamarin project. Yes, you can just use the default information that comes with a project. If you’re like me though, you have some questions and some things just didn’t add up. I searched around and found several walkthroughs, but none that could get the information to just click. This is just a VERY basic project that allows the user to type something, then it be replicated on the following line. When the user is finished, they have a reset button that clears all the text. Yes, there are other ways to do what I have here, this is just my interpretation. In this project, we will use Xamarin, MvvmCross, and XAML. If you follow along, this should give you the basics to get you started on your own project. Even though Xamarin can be used for Android, iOS, and Windows, in this walkthrough, we will just be concerned with Android and Windows Desktop. Once you can get the concept of the two, adding in anything else is not a stretch.
Background
When I was trying to pick this up, I had nothing but trouble trying to find a good tutorial. I swore if I could understand this, I was going to try and help others.
Prerequisites
To do this tutorial, you will need Visual Studio 2017, Android SDK, and Xamarin for Visual Studio.
Using the Code
To start everything off, open Visual Studio. Once the IDE has opened, navigate to the menu bar and select File -> New -> Project. Once the window has opened, to the far right is a Search bar. In there, type Blank. Here, you will select "Blank Solution" in the middle view of the window. Let’s go ahead and name the new solution TextExample
. For the location, you can place it wherever you want. I like to place mine in pre-defined locations. So, mine will be in "C:\Mobile".
Once you have everything entered, press the OK button. With the new solution showing in the Solution Explorer, let’s start adding projects. The first project that we are going to add is the core project. Right click on the solution and select Add -> New Project. From here, if you have everything pre-installed, you should see Cross-Platform on the far-left column. Select it, then select Class Library (Xamarin.Forms
) in the middle section of the window. Go ahead and name the new project as TextExample.Core
, and hit the OK button.
When this first comes up, it is going to show errors. Do not worry about this right now. We will fix this as we move on. The next thing that we are going to do is add our next project. So, like before, right click on the solution and navigate to Add -> New Project. This time, we will select Android from the far-left column. Once you have selected Android, you should see Blank App (Android) in the center column. Select this and name the new project TextExample.Droid
and hit the OK button.
When the Droid project has finished loading and comes up, we will add one more project to the solution. By now, you should be an expert at this, go to the solution and right click on it, navigate to Add -> New Project. When the window comes up, select Windows Classic Desktop to the far-left column. Once selected, choose WPF App (.NET Framework) in the middle column. Go ahead and name the project TextExample.WPF
and hit the OK button.
Now that all three projects have been created, we can start the process of tying things together. The first part of that is to right click on the solution and select Manage Nuget Packages for Solution.
Before we can add anything here, we should make sure that there are no updates available. If you have updates present, go ahead and run them. Once you have verified that your packages are up to date, click on the Browse tab. From here, click in the search box and type in MvvmCross.StarterPack
. In the results that show up, select MvvmCross.StarterPack
by MvvmCross
. To the right, an area should now show your solution. Select the top check box next to Project, this will select all projects. Then hit the Install button.
Once the package has finished installing, the Output window will show a finished acknowledgement.
Now that we have the package fully loaded, we can start the work. The first thing that we need to do is start in the core project. Once you are in the core project, look for the file TextExample.Core.cs. Right click on this file and delete it. Next locate the ViewModels folder. Once you find it, expand it out and delete the MainViewModels.cs file. Yes, we could just use the default file, but doing it yourself generally helps more to make the connection. If this layout is unfamiliar to you, this core project is where you will have all of your "business logic". By putting all of this code in one location, you can better test your basic logic. Once all of the logic has been tested, it shouldn’t need to be tested again unless you add a new feature to it. No matter what other projects you have connected to it, this will always stay the same. With that said, right click on the ViewModels folder and select Add -> Class. Let’s go ahead and name it, name the new class TextViewModel
. In here, we are going to place all of our logic that we want the applications to follow. The first thing we need to do is make the class a public
class and then add an inheritance from MvxViewModel
. This inheritance will allow the view model to be seen and be connected to later. Inside this class, you need to add two properties. Name them Edit Text and Copy Text. As I stated before, we are keeping this very basic! You will also need to make a method called ClearTextValue
and an ICommand
named ResetTextCommand
. The ClearTextValue
method will just clear the text going to the UI. The ResetTextCommand
will be the command that the UI calls through binding. Below is a screen of the code.
using MvvmCross.Core.ViewModels;
using System;
using System.Windows.Input;
namespace TextExample.Core.ViewModels
{
public class TextViewModel : MvxViewModel
{
private string editText = String.Empty;
private string copyText = String.Empty;
#region Constructor
public TextViewModel() { }
#endregion
#region Properties
public string EditText
{
get { return this.editText; }
set
{
this.editText = value;
this.CopyText = this.editText;
this.RaisePropertyChanged(() => EditText);
}
}
public string CopyText
{
get { return this.copyText; }
set
{
this.copyText = value;
this.RaisePropertyChanged(() => CopyText);
}
}
#endregion
#region Methods
private void ClearTextValue()
{
this.EditText = String.Empty;
}
#endregion
#region Commands
public ICommand ResetTextCommand
{
get { return new MvxCommand(() => ClearTextValue()); }
}
#endregion
}
}
With that code added, find the App.cs file and open it. Once open, locate the line that has RegisterAppStart
. There, you will need to replace the line with the following:
RegisterNavigationServiceAppStart<ViewModels.TextViewModel>();
By doing this, you are telling the application what view model to look for. That is the last thing that we should have to do for this project.
The next project that we are going to get into is the TextExample.Droid
. The first thing to do here is to locate the folder named ToDo-MvvmCross. Expand this folder and follow the instructions. If by some chance, you do not find this folder or the instructions. You need to add a reference to the TextExample.Core
Project. To do this, right click on References in the TextExample.Droid
project and select Add Reference. From here, you should see TextExample.Core
. Select it, DO NOT select TextExample.WPF
. The next thing that the instructions tell you is to delete the file named MainActivity.cs. So, locate it and right click and delete. I am one to clean up when I am done, so I deleted more items. I also removed the ToDo-MvvmCross folder and the GettingStarted.Xamarin
file. Since we are in a deleting mode. Let's also remove MainView.axml located under Resources -> layout. Also remove MainView.cs from the Views folder. With those files gone, right click on newly expanded layout folder and select Add -> New Item. From the pop up window, select Android Layout in the middle column. Name the new layout TextView.axml. After the layout gets done loading, go ahead and add the following to your layout 1 EditText
control, 1 TextView
(Large) Control, and 1 button
. I find it easier to add them from the source tab. Once you have the controls loaded on the view, you will need to change to the view to the source tab. On here, you will need to add a view items. On the LinearLayout
tag, you will need to add xmlns:local="http://schemas.android.com/apk/res-auto"
. On your EditText
control, you need to add:
android:id="@+id/textViewEdit"
android:focusable="true"
android:focusableInTouchMode="true"
local:MvxBind="Text EditText"
Here, the id
will be the name of the object, the focusable lines will deal with bringing up a keyboard, and the important one here will be the MvxBind
. Here you can see that the first value is Text
. This tells the code what it is binding. The second value is EditText
. If you remember from the view model, we have a property named EditText
. This value is now linked to this object. On your TextView
control, you need to add:
android:id="@+id/textViewCopy"
local:MvxBind="Text CopyText"
Again, this is the name of the object and then setting the binding on the object. The last thing on this view is the button
. On this, you will need to add:
android:id="@+id/buttonReset"
local:MvxBind="Click ResetTextCommand"
Just like the text controls earlier, the id
is the name of the object. On this one, the first value is Click
. So, we are saying that on a click event bind something. The second value tells it to bind to an ICommand
property located on the view model. Your source code should look just like mine now.
="1.0"="utf-8"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_width="match_parent"
android:layout_height="wrap_parent"
android:id="@+id/textViewEdit"
android:focusable="true"
android:focusableInTouchMode="true"
android:MvxBind="Text EditText" />
<TextView android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_width="match_parent"
android:layout_height="wrap_parent"
android:id="@+id/textViewCopy"
android:MvxBind="Text CopyText" />
<Button android:text="Reset"
android:layout_width="match_parent"
android:layout_height="wrap_parent"
android:id="@+id/buttonReset"
android:MvxBind="Click ResetTextCommand" />
</LinearLayout>
Now that we have setup the view, we have a few last-minute things to take care of before we leave this project. First, we need to right click on the Views folder and then select Add -> Class. Name this new class TextView.cs. Here, you will need to add a line above the class like the following:
[Activity(Label = "View for Text View Model",
WindowSoftInputMode = SoftInput.StateVisible)]
With that in place, make the class public
and add an inheritance to MvxActivity
. After that, insert the protected
method OnCreate
in the class. Then add the following:
base.OnCreate(bundle);
SetContentView(Resource.Layout.TextView);
Button button = FindViewById<Button>(Resource.Id.buttonReset);
EditText etKeyboard = FindViewById<EditText>(Resource.Id.textViewEdit);
InputMethodManager mgr = (InputMethodManager)GetSystemService
(Context.InputMethodService);
mgr.ShowSoftInput(etKeyboard, ShowFlags.Implicit);
Now your TextView.cs should look like mine.
using Android.App;
using Android.Content;
using Android.OS;
using Android.Views;
using Android.Widget;
using MvvmCross.Droid.Views;
using Android.Views.InputMethods;
namespace TextExample.Droid.Views
{
[Activity(Label = "View for Text View Model",
WindowSoftInputMode = SoftInput.StateVisible)]
public class TextView : MvxActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.TextView);
Button button = FindViewById<Button>
(Resource.Id.buttonReset);
EditText etKeyboard = FindViewById<EditText>
(Resource.Id.textViewEdit);
InputMethodManager mgr =
(InputMethodManager)GetSystemService(Context.InputMethodService);
mgr.ShowSoftInput(etKeyboard, ShowFlags.Implicit);
}
}
}
Now find and open the file Splashscreen.cs. In here, you are going to remove one line. Remove the line that says:
, Icon = "@mipmap/icon"
All this does is reference an icon file that we are not going to use.
We are almost done here. We are finished with all the work that we are going to do to the Droid project. Now we are going to work on the WPF project. The first thing that we need to do here is add a reference to the Core project. So, locate References, then right click and select Add Reference. From here, select TextExample.Core
. Like before, DO NOT select TextExample.Droid
. With that finished, right click and delete the ToDo-MvvmCross folder. Now expand the Views folder and right click and delete the file MainView.xaml. With that deleted, let's add our own view. Right click on the folder and select Add -> UserControl. Go ahead and name it TextView.xaml and then hit the OK button. For all the work that has to be done in this file, it is just easier to do it in XAML view. In here, you will need to change the main tag to views:MvxWpfView
. This should change both on top at the end of the tag. If not, adjust it accordingly. Now, we will need to add some usings to the control. Add the following to the main tag:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:views="clr-namespace:MvvmCross.Wpf.Views;assembly=MvvmCross.Wpf"
Now remove the grid control. In its place, put in a StackPanel
. In that stack panel, place the following in this order, textbox
, textblock
, button
. For the TextBox
, add the following:
x:Name="textBoxEdit"
Text="{Binding EditText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
So, what did we just add? The first thing we did was name the control. The second thing we did is the important thing. Here, we added in binding back to the view model. We told the control to bind to the EditText
property. Then, we told it that it is a two binding and to update the binding when the property changes. For the TextBlock
, add the following:
x:Name="textBlockCopy"
Text="{Binding CopyText, Mode=OneWay}"
Just like before, here we named the control then set up the binding. Unlike before, here we only want the control to bind in one direction. The final thing that we are going to do in the xaml is the button. Add the following to the button
:
x:Name="buttonReset"
Content="Reset"
Command="{Binding ResetTextCommand}"
Just like the others, here we set the controls name. Here though, instead of setting a text binding, we are setting the command binding. This will tell the control that anytime the button is hit follow this property. Your XAML file should now look like this:
<views:MvxWpfView x:Class="TextExample.WPF.Views.TextView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:views="clr-namespace:MvvmCross.Wpf.Views;assembly=MvvmCross.Wpf"
xmlns:local="clr-namespace:TextExample.WPF.Views"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="300">
<StackPanel>
<TextBox x:Name="textBoxEdit"
Text="{Binding EditText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock x:Name="textBlockCopy"
Text="{Binding CopyText, Mode=OneWay}" />
<Button x:Name="buttonReset"
Content="Reset"
Command="{Binding ResetTextCommand}" />
</StackPanel>
</views:MvxWpfView>
Once your file looks like mine, put your mouse in the main window and right click. Here a list should come up. Select the option for View Code. This takes you to the code behind of the user control. In here change the inheritance from UserControl
to MvxWpfView
. Your code behind should look like the following:
using MvvmCross.Wpf.Views;
namespace TextExample.WPF.Views
{
public partial class TextView : MvxWpfView
{
public TextView()
{
InitializeComponent();
}
}
}
With that, all the coding is finished. You can right click on the solution and select Build. Everything should build successfully:
Now if you want to run the any of the new applications, you can just right click on that project and select Set As StartUp Project. Once you do this, you can just click the Start button to run it. Keep in mind that to run the Android project, you must already have the Android SDK installed.
Conclusion
I hope that this article has helped you. If you have any issues with this code, I have included a link to the code source.
History
- 3rd January, 2018: Initial version