65.9K
CodeProject 正在变化。 阅读更多。
Home

Xamarin 和 MvvmCross: 初学者简单教程

starIconstarIconstarIconstarIconstarIcon

5.00/5 (5投票s)

2018 年 1 月 3 日

CDDL

11分钟阅读

viewsIcon

25264

downloadIcon

804

Xamarin 和 MvvmCross: 初学者简单教程。

引言

本教程的目的是帮助您快速上手一个 Xamarin 项目。是的,您也可以直接使用项目附带的默认信息。但是,如果您像我一样,您会有一些疑问,并且有些事情就是解释不通。我搜索了很多,找到了几个教程,但没有一个能让我真正理解。这是一个非常基础的项目,它允许用户输入一些内容,然后在下一行重复显示。当用户完成时,他们有一个重置按钮可以清除所有文本。是的,还有其他方法可以实现我在这里所做的,这只是我的个人理解。在这个项目中,我们将使用 Xamarin、MvvmCross 和 XAML。如果您跟着做,应该就能获得入门的基础知识,以便开始您自己的项目。尽管 Xamarin 可用于 Android、iOS 和 Windows,但在本教程中,我们只关注 Android 和 Windows 桌面。一旦您理解了这两个平台的概念,添加其他内容就不会很困难。

背景

当我尝试学习这些的时候,我找一个好的教程简直困难重重。我发誓,如果我能理解这一点,我一定要帮助其他人。

必备组件

要完成本教程,您需要 Visual Studio 2017、Android SDK 和 Visual Studio 的 Xamarin。

Using the Code

要开始一切,请打开 **Visual Studio**。IDE 打开后,导航到菜单栏并选择 **文件** -> **新建** -> **项目**。窗口打开后,右侧有一个搜索栏。在那里,键入 **Blank**。在这里,您将在窗口的中间视图中选择“**Blank Solution**”。让我们将新解决方案命名为 `TextExample`。位置可以放在您想要的任何地方。我喜欢将我的放在预定义的目录中。所以,我的将是“*C:\Mobile*”。

输入所有信息后,按 **OK** 按钮。在新解决方案显示在 **Solution Explorer** 中后,让我们开始添加项目。我们要添加的第一个项目是核心项目。右键单击解决方案,然后选择 **Add** -> **New Project**。从这里,如果您预装了所有内容,应该会在最左侧的列中看到 Cross-Platform。选择它,然后在窗口中间部分选择 Class Library (Xamarin.Forms)。将新项目命名为 `TextExample.Core`,然后按 **OK** 按钮。

当这个项目首次出现时,它会显示错误。现在不用担心。我们将在接下来的步骤中解决这些问题。接下来我们要添加下一个项目。所以,和之前一样,右键单击解决方案并导航到 **Add** -> **New Project**。这次,我们将从最左侧的列中选择 Android。选择 Android 后,您应该会在中间列中看到 Blank App (Android)。选择它,并将新项目命名为 `TextExample.Droid`,然后按 **OK** 按钮。

当 Droid 项目完成加载并显示出来时,我们将向解决方案添加最后一个项目。到目前为止,您应该已经熟练了,右键单击解决方案,导航到 **Add** -> **New Project**。窗口出现后,在最左侧列选择 **Windows Classic Desktop**。选择后,在中间列中选择 WPF App (.NET Framework)。将项目命名为 `TextExample.WPF`,然后按 **OK** 按钮。

现在所有三个项目都已创建,我们可以开始将它们连接起来的过程。第一步是右键单击解决方案并选择 **Manage Nuget Packages for Solution**。

在添加任何内容之前,我们应该确保没有可用的更新。如果有更新,请进行更新。验证完包是最新的之后,单击 **Browse** 选项卡。在这里,单击搜索框并键入 `MvvmCross.StarterPack`。在显示的结果中,选择 `MvvmCross` 的 `MvvmCross.StarterPack`。右侧应该会显示您的解决方案。选中 **Project** 旁边的顶部复选框,这将选择所有项目。然后按 **Install** 按钮。

包安装完成后,Output 窗口将显示完成确认。

现在包已完全加载,我们可以开始工作了。第一件事是开始处理核心项目。进入核心项目后,找到文件 *TextExample.Core.cs*。右键单击此文件并删除它。接下来找到 *ViewModels* 文件夹。找到后,展开它并删除 *MainViewModels.cs* 文件。是的,我们可以使用默认文件,但自己动手通常更有助于建立联系。如果您不熟悉此布局,此核心项目是您放置所有“业务逻辑”的地方。将所有代码放在一个位置,您可以更好地测试您的基本逻辑。一旦所有逻辑都经过测试,除非您添加新功能,否则无需再次测试。无论您连接了其他什么项目,它都将保持不变。话虽如此,右键单击 *ViewModels* 文件夹并选择 **Add** -> **Class**。让我们将其命名为 `TextViewModel`。在这里,我们将放置应用程序遵循的所有逻辑。第一件事是使类成为 `public` 类,然后添加对 `MvxViewModel` 的继承。此继承将允许视图模型被看到并在以后连接。在此类中,您需要添加两个属性。将它们命名为 **EditText** 和 **Copy Text**。正如我之前所说,我们保持这个非常基础!您还需要创建一个名为 `ClearTextValue` 的方法和一个名为 `ResetTextCommand` 的 `ICommand`。 `ClearTextValue` 方法将清除要发送到 UI 的文本。 `ResetTextCommand` 将是 UI 通过绑定调用的命令。代码屏幕如下所示。

        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
            }
        }

添加完代码后,找到 *App.cs* 文件并打开它。打开后,找到包含 `RegisterAppStart` 的行。在那里,您需要用以下内容替换该行

     RegisterNavigationServiceAppStart<ViewModels.TextViewModel>();

通过这样做,您告诉应用程序要查找哪个视图模型。这是我们为该项目需要做的最后一件事。

接下来我们要处理的项目是 `TextExample.Droid`。首先要做的就是找到名为 *ToDo-MvvmCross* 的文件夹。展开此文件夹并按照说明进行操作。如果碰巧找不到此文件夹或说明,您需要添加对 `TextExample.Core` 项目的引用。为此,请右键单击 `TextExample.Droid` 项目中的 **References**,然后选择 **Add Reference**。从这里,您应该看到 `TextExample.Core`。选择它,**不要**选择 `TextExample.WPF`。接下来说明告诉您删除名为 *MainActivity.cs* 的文件。所以,找到它并右键单击并删除。我喜欢在完成后进行清理,所以我删除了更多项目。我还删除了 *ToDo-MvvmCross* 文件夹和 `GettingStarted.Xamarin` 文件。既然我们在删除模式下。让我们也删除 **Resources** -> **layout** 下的 *MainView.axml*。还从 Views 文件夹中删除 *MainView.cs*。删除这些文件后,右键单击新展开的 layout 文件夹并选择 **Add** -> **New Item**。在弹出的窗口中,在中间列选择 Android Layout。将新布局命名为 *TextView.axml*。布局加载完成后,请在布局中添加 1 个 `EditText` 控件,1 个 `TextView` (Large) 控件,以及 1 个 `button`。我发现从源选项卡添加它们更容易。加载完控件后,您需要将视图切换到源选项卡。在这里,您需要添加视图项。在 `LinearLayout` 标签上,您需要添加 `xmlns:local="http://schemas.android.com/apk/res-auto"`。在 `EditText` 控件上,您需要添加

    android:id="@+id/textViewEdit"
    android:focusable="true"
    android:focusableInTouchMode="true"
    local:MvxBind="Text EditText"

在这里,`id` 将是对象的名称,`focusable` 行将处理调出键盘,而重要的一个将是 `MvxBind`。在这里您可以看到第一个值是 `Text`。这告诉代码它正在绑定什么。第二个值是 `EditText`。如果您还记得视图模型,我们有一个名为 `EditText` 的属性。此值现在已链接到此对象。在 `TextView` 控件上,您需要添加

    android:id="@+id/textViewCopy"
    local:MvxBind="Text CopyText"

同样,这是对象的名称,然后设置对象上的绑定。在此视图上的最后一项是 `button`。在此,您需要添加

    android:id="@+id/buttonReset"
    local:MvxBind="Click ResetTextCommand"

就像之前的文本控件一样,`id` 是对象的名称。在这里,第一个值是 `Click`。所以,我们说当点击事件发生时绑定某些东西。第二个值告诉它绑定到视图模型上位于的 `ICommand` 属性。您的源代码现在应该和我的一样。

<?xml version="1.0" encoding="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>

现在我们已经设置好了视图,在离开这个项目之前还有一些最后的事情要处理。首先,我们需要右键单击 *Views* 文件夹,然后选择 **Add** -> **Class**。将这个新类命名为 *TextView.cs*。在这里,您需要在类上方添加一行,如下所示

    [Activity(Label = "View for Text View Model", 
     WindowSoftInputMode = SoftInput.StateVisible)]

有了这个之后,将类设为 `public` 并继承 `MvxActivity`。之后,在类中插入 `protected` 方法 `OnCreate`。然后添加以下内容

    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);

现在您的 *TextView.cs* 应该和我的看起来一样。

    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);
            }
        }
    }

现在找到并打开文件 *Splashscreen.cs*。在这里,您需要删除一行。删除写着

    , Icon = "@mipmap/icon"

这只是引用了一个我们不打算使用的图标文件。

我们快完成了。我们已经完成了对 Droid 项目的所有工作。现在我们将开始处理 WPF 项目。首先要做的就是添加对 Core 项目的引用。所以,找到 **References**,然后右键单击并选择 **Add Reference**。从这里,选择 `TextExample.Core`。和之前一样,**不要**选择 `TextExample.Droid`。完成此操作后,右键单击并删除 *ToDo-MvvmCross* 文件夹。现在展开 *Views* 文件夹,右键单击并删除文件 *MainView.xaml*。删除后,让我们添加自己的视图。右键单击文件夹并选择 **Add** -> **UserControl**。将它命名为 *TextView.xaml*,然后按 **OK** 按钮。对于在此文件中完成的所有工作,在 XAML 视图中完成会更容易。在这里,您需要将主标签更改为 `views:MvxWpfView`。这应该在标签顶部的末尾处都发生更改。如果没有,请相应地调整。现在,我们需要向控件添加一些 using。将以下内容添加到主标签

    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:views="clr-namespace:MvvmCross.Wpf.Views;assembly=MvvmCross.Wpf"

现在删除 grid 控件。取而代之的是,放入一个 `StackPanel`。在该 stack panel 中,按以下顺序放置:`textbox`、`textblock`、`button`。对于 `TextBox`,添加以下内容

    x:Name="textBoxEdit"
    Text="{Binding EditText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"

那么,我们刚才添加了什么?我们做的第一件事是命名控件。我们做的第二件事是最重要的。在这里,我们添加了回溯到视图模型的绑定。我们告诉控件绑定到 `EditText` 属性。然后,我们告诉它这是双向绑定,并在属性更改时更新绑定。对于 `TextBlock`,添加以下内容

    x:Name="textBlockCopy"
    Text="{Binding CopyText, Mode=OneWay}"

和之前一样,这里我们命名了控件然后设置了绑定。与之前不同的是,这里我们只希望控件单向绑定。在 xaml 中我们要做的最后一件事是按钮。将以下内容添加到 `button`

    x:Name="buttonReset"
    Content="Reset"
    Command="{Binding ResetTextCommand}"

就像其他控件一样,这里我们设置了控件的名称。这里,我们没有设置文本绑定,而是设置了命令绑定。这将告诉控件,只要按钮被按下,就遵循此属性。您的 XAML 文件现在应该看起来像这样

    <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>

一旦您的文件看起来和我的一样,将鼠标放在主窗口上并右键单击。此时应该会出现一个列表。选择 View Code 选项。这会将您带到用户控件的代码隐藏。在这里,将继承从 `UserControl` 更改为 `MvxWpfView`。您的代码隐藏应该如下所示

    using MvvmCross.Wpf.Views;

    namespace TextExample.WPF.Views
    {
        /// <summary>
        /// Interaction logic for TextView.xaml
        /// </summary>
        public partial class TextView : MvxWpfView
        {
            public TextView()
            {
                InitializeComponent();
            }
        }
    }

完成后,所有编码就完成了。您可以右键单击解决方案并选择 **Build**。一切都应该成功构建

New Project Base Image

现在,如果您想运行任何新应用程序,只需右键单击该项目并选择 **Set As StartUp Project**。执行此操作后,只需单击 **Start** 按钮即可运行。请记住,要运行 Android 项目,您必须已经安装了 Android SDK。

结论

希望本文对您有所帮助。如果您对此代码有任何问题,我已经包含了一个指向源代码的链接。

历史

  • 2018 年 1 月 3 日:初始版本
© . All rights reserved.