Xamarin.Forms 是一个开放源代码 UI 框架。
通过 Xamarin.Forms,开发人员可从单个共享基本代码生成 Xamarin.Android、Xamarin.iOS 和 Windows 应用程序。
Xamarin.Forms 优点 :可以跨平台的构建用户交互相关的东西,简而言之就是写一套代码三个平台通用,在此基础上也能够结合各平台特有的Xamarin本地代码混合一起。
Forms除了跨平台的好处之外,还支持Xaml编写用户界面,不用借助Goft.Mvvm.light等第三方框架原生支持数据绑定等。

这些项目如下:

  • Notes - 此项目是 .NET Standard 库项目,其中包含所有共享逻辑代码和共享 UI。
  • Notes.Android - 此项目包含 Android 特定代码,是 Android 应用程序的入口点。
  • Notes.iOS - 此项目包含 iOS 特定代码,是 iOS 应用程序的入口点。
  • Notes.UWP - 此项目包含通用 Windows 平台特定代码,是 UWP 应用程序的入口点。
    在这里插入图片描述
    Xamarin.Forms 应用程序采用与传统跨平台应用程序相同的构建方式。 共享代码通常位于 .NET Standard 库中,平台特定应用程序将使用此共享代码。 下图概要演示了 Notes 应用程序的这种关系:
    在这里插入图片描述
    若要最大限度重用启动代码,Xamarin.Forms 应用程序需有一个名为 App 的单个类,该类负责实例化应用程序在 每个平台上将显示的首页 ,如以下代码示例所示:
using Xamarin.Forms;
namespace Notes
    public partial class App : Application
        public App()
            InitializeComponent();
            MainPage = new NavigationPage(new NotesPage());
        ...

本质是将页面放入堆栈 每次pop栈顶元素

await Navigation.PopAsync();

4 个主要控件组创建 Xamarin.Forms 应用程序的用户界面

  • 页面
  • 视图
  • 布局
  • 单元格

数据绑定连接两个对象,即源和目标。 源对象提供数据。 目标对象使用(并经常显示)来自源对象的数据。
例如,Editor(目标对象)通常会将其 Text 属性绑定到源对象中的公共 string 属性。 下图说明了这种绑定关系:
在这里插入图片描述
幕后的绑定框架源会将源对象中的更改自动推送到目标对象,且目标对象中的更改可选择性地推送回源对象。
创建数据绑定只需两个步骤:

  • 目标对象的 BindingContext 属性必须设置为
  • 必须在目标和源之间建立绑定。 在 XAML 中,此过程可通过使用 Binding 标记扩展实现。

在 Notes 应用程序中,绑定目标是显示便笺的 Editor,而设置为 NoteEntryPage 的 BindingContext 的 Note 实例是绑定源。
NoteEntryPage 的 BindingContext 在页面导航过程中进行设置,如下面的代码示例所示:

async void OnNoteAddedClicked(object sender, EventArgs e)
    await Navigation.PushAsync(new NoteEntryPage
        BindingContext = new Note()
    });
async void OnListViewItemSelected(object sender, SelectedItemChangedEventArgs e)
    if (e.SelectedItem != null)
        await Navigation.PushAsync(new NoteEntryPage
            BindingContext = e.SelectedItem as Note
        });

NoteEntryPage 中的 Editor 随后会绑定到 Note 对象的 Text 属性:

<Editor Placeholder="Enter your note"
        Text="{Binding Text}"
        ... />

Editor.Text 属性和源 对象的 Text 属性之间建立绑定。
Editor 中所做的更改将自动传播到 Note 对象。 同样,如果更改了 Note.Text 属性,Xamarin.Forms 绑定引擎也会更新 Editor 的内容。 这称为双向绑定

首先定义一个 Note 模型,该模型将在应用程序中存储有关每个便笺的数据。 使用 PrimaryKey 和 AutoIncrement 特性标记 ID 属性,以确保 SQLite.NET 数据库中的每个 Note 实例均具有 SQLite.NET 提供的唯一 ID。

using System;
using SQLite;
namespace Notes.Models
    public class Note
        [PrimaryKey, AutoIncrement]
        public int ID { get; set; }
        public string Text { get; set; }
        public DateTime Date { get; set; }

接下来创建数据库、从中读取数据、向其写入数据以及从中删除数据
代码使用将数据库操作移动到后台线程的异步 SQLite.NET API。

using System.Collections.Generic;
using System.Threading.Tasks;
using SQLite;
using Notes.Models;
namespace Notes.Data
    public class NoteDatabase
        readonly SQLiteAsyncConnection _database;
		//此外,NoteDatabase 构造函数将数据库文件的路径作为参数。
        public NoteDatabase(string dbPath)
            _database = new SQLiteAsyncConnection(dbPath);
            _database.CreateTableAsync<Note>().Wait();
        public Task<List<Note>> GetNotesAsync()
            return _database.Table<Note>().ToListAsync();
        public Task<Note> GetNoteAsync(int id)
            return _database.Table<Note>()
                            .Where(i => i.ID == id)
                            .FirstOrDefaultAsync();
        public Task<int> SaveNoteAsync(Note note)
            if (note.ID != 0)
                return _database.UpdateAsync(note);
                return _database.InsertAsync(note);
        public Task<int> DeleteNoteAsync(Note note)
            return _database.DeleteAsync(note);

以下代码定义一个 Database 属性,该属性以单一实例的形式创建新 NoteDatabase 实例,将数据库的文件名作为参数传入 NoteDatabase 构造函数。
以单一实例的形式公开数据库的优势是,所创建的单一数据库连接在应用程序运行时保持打开状态,因此避免了每次执行数据库操作时打开和关闭数据库文件所产生的费用。类似于设计模式中的单例模式

using System;
using System.IO;
using Xamarin.Forms;
using Notes.Data;
namespace Notes
    public partial class App : Application
        static NoteDatabase database;
        public static NoteDatabase Database
                if (database == null)
                    database = new NoteDatabase(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Notes.db3"));
                return database;
        public App()
            InitializeComponent();
            MainPage = new NavigationPage(new NotesPage());
        protected override void OnStart()
            // Handle when your app starts
        protected override void OnSleep()
            // Handle when your app sleeps
        protected override void OnResume()
            // Handle when your app resumes

StackLayout

StackLayout 中子视图的大小和位置取决于子视图 属性的值。
HorizontalOptions 使用从父布局的 X 轴中的剩余空间
VerticalOptions 使用从父布局在 Y 轴的剩余空间。
如果多个子级的布局设置为展开,按比例分配额外的空间。
HeightRequest WidthRequest 分别代表高度和宽度

Lable

设置更改 Label 视觉外观的属性。
TextColor 属性设置 Label 文本的颜色。 FontAttributes 属性将标签的字体设置为斜体,FontSize 属性设置字号。
此外,通过设置 TextDecorations 属性向 Label 应用下划线文本效果,并通过将 HorizontalOptions 属性设置为 Center 使其水平居中。

<Label Text="Welcome to Xamarin.Forms!"
       TextColor="Blue"
       FontAttributes="Italic"
       FontSize="22"
       TextDecorations="Underline"
       HorizontalOptions="Center" />

Button

此代码将 Clicked 事件设置为将在下一步中创建的名为 OnButtonClicked 的事件处理程序。

<Button Text="Click me"
        Clicked="OnButtonClicked" /> 

点击 Button 时,将执行 OnButtonClicked 方法。 sender 参数是负责触发 Clicked 事件的 Button 对象,还可用于访问 Button 对象。 此事件处理程序更新 Button 显示的文本。

void OnButtonClicked(object sender, EventArgs e)
    (sender as Button).Text = "Click me again!";

修改 Button 声明,改变其视觉外观
此代码设置更改 Button 视觉外观的属性。 TextColor 属性设置 Button 文本的颜色,BackgroundColor 属性设置文本背景的颜色。 BorderColor 属性设置 Button 周围区域的颜色,BorderWidth 属性设置边框的宽度。 默认情况下,Button 是矩形,但可以通过将 CornerRadius 属性设置为合适的值来设定圆角。 另外,通过设置 WidthRequest 和 HeightRequest 属性来改变 Button 的大小。

<Button Text="Click me"
        Clicked="OnButtonClicked"
        TextColor="Blue"
        BackgroundColor="Aqua"
        BorderColor="Red"
        BorderWidth="5"
        CornerRadius="5"
        WidthRequest="150"
        HeightRequest="75" />

Entry

TextChanged 事件设置为名为 OnEntryTextChanged 的事件处理程序,将 Completed 事件设置为名为 OnEntryCompleted 的事件处理程序。

<Entry Placeholder="Enter text"
       TextChanged="OnEntryTextChanged"
       Completed="OnEntryCompleted" />

当 Entry 中的文本更改时,将执行 OnEntryTextChanged 方法。 sender 参数是负责触发 TextChanged 事件的 Entry 对象,还可用于访问 Entry 对象。 TextChangedEventArgs 参数提供了文本更改之前和之后的旧文本值和新文本值。
使用返回键完成 Entry 中的文本时,将执行 OnEntryCompleted 方法。 sender 参数是负责触发 TextChanged 事件的 Entry 对象,还可用于访问 Entry 对象。
向 Entry 输入的任何文本都将存储在 Text 属性中。

void OnEntryTextChanged(object sender, TextChangedEventArgs e)
    string oldText = e.OldTextValue;
    string newText = e.NewTextValue;
void OnEntryCompleted(object sender, EventArgs e)
    string text = ((Entry)sender).Text;

自定义 Entry 行为的属性。 MaxLength 属性限制允许的 Entry 输入长度,将 IsSpellCheckEnabled 属性设置为 false 以禁用拼写检查。 同样,将 IsTextPredictionEnabled 属性设置为 false 以禁用文本预测和自动文本预测。 此外,IsPassword 属性确保使用密码字符(黑色圆圈)对输入的字符进行掩码。

<Entry Placeholder="Enter password"
       MaxLength="15"
       IsSpellCheckEnabled="false"
       IsTextPredictionEnabled="false"
       IsPassword="true" />

create app with xaml and c#

同样的UI 用xaml和c# 只是在共享代码段不同
在这里插入图片描述 在这里插入图片描述
同样的MVVM、Navigation 用xaml和c# 只是在公用代码段的 Views 不同 models 和 viewModels 都是一样的
在这里插入图片描述 在这里插入图片描述

xaml 用来定义UI 像xml 但是多出了binding 和command 功能 和创造 出色的UI界面
除此之外 xaml 支持 hot-Reload 热加载 和 预览器
Xamarin 的XAML是 热重载的 改动save后 会立即显示
官网的热重载解释
hot-reload 好处是当我们修改xaml后 不需要restart project
在这里插入图片描述

xamarin.form UI with xaml

最外层是Grid控件,这个在wpf中是一个布局控件,就跟将窗体设置单元格差不过,可以依据它的row和column属性来设置行和列。 如下图 “*”=star 代表比例
在这里插入图片描述
在这里插入图片描述

//span跨越两列,因为一共2列所以是居中

xamarin.form MVVM in xaml

model = data view = UI viewModal 连接data 和UI层的 并且对它绑定的操作做出反应的逻辑层
如下图所示 INotifyPropertyChanged 用来监视 其绑定的属性值是否更改
在这里插入图片描述
在view 层我们设置binding 的command 当点击此button 会跳转到 viewmodel 进行相应逻辑操作
在这里插入图片描述
在这里插入图片描述

single page UI in c#

Editor

noteEditor = new Editor
     Placeholder = "Enter Note", 	//text无填写的情况下默认显示
     BackgroundColor = Color.White,
     Margin = new Thickness(10)		//离左右边界的厚度

属性说明:
star 数值2:1 表示 不同的列所占用该行空间的比例
absolute 定义一个精确的像素或点密度
auto 自动 (不推荐)

ColumnDefinitions =
   new ColumnDefinition { Width = new GridLength(2, GridUnitType.Star) },
   new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }
grid.Children.Add(xamagonImage, 0, 0);	//将image放在col=0 row=0
Grid.SetColumnSpan(xamagonImage, 2); //span跨越两列因为一共2列所以是居中
using Xamarin.Forms;
namespace CodedUIMvvm
    public class MainPage: ContentPage
        public MainPage()
            BackgroundColor = Color.PowderBlue;
            BindingContext = new MainPageViewModel();
            var xamagonImage = new Image
                Source = "xamagon.png"
            var noteEditor = new Editor
                Placeholder = "Enter Note",
                BackgroundColor = Color.White,
                Margin = new Thickness(10)
            noteEditor.SetBinding(Editor.TextProperty, nameof(MainPageViewModel.NoteText));
            var saveButton = new Button
                Text = "Save",
                TextColor = Color.White,
                BackgroundColor = Color.Green,
                Margin = new Thickness(10)
            saveButton.SetBinding(Button.CommandProperty, nameof(MainPageViewModel.SaveNoteCommand));
            var deleteButton = new Button
                Text = "Delete",
                TextColor = Color.White,
                BackgroundColor = Color.Red,
                Margin = new Thickness(10)
            deleteButton.SetBinding(Button.CommandProperty, nameof(MainPageViewModel.EraseNotesCommand));
            var collectionView = new CollectionView
                ItemTemplate = new NotesTemplate()
            collectionView.SetBinding(CollectionView.ItemsSourceProperty, nameof(MainPageViewModel.Notes));
            var grid = new Grid
                Margin = new Thickness(20, 40),
                ColumnDefinitions =
                    new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) },
                    new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }
                RowDefinitions =
                    new RowDefinition { Height = new GridLength(1.0, GridUnitType.Star) },
                    new RowDefinition { Height = new GridLength(2.5, GridUnitType.Star) },
                    new RowDefinition { Height = new GridLength(1.0, GridUnitType.Star) },
                    new RowDefinition { Height = new GridLength(2.0, GridUnitType.Star) },
            grid.Children.Add(xamagonImage, 0, 0);
            Grid.SetColumnSpan(xamagonImage, 2);
            grid.Children.Add(noteEditor, 0, 1);
            Grid.SetColumnSpan(noteEditor, 2);
            grid.Children.Add(saveButton, 0, 2);
            grid.Children.Add(deleteButton, 1, 2);
            grid.Children.Add(collectionView, 0, 3);
            Grid.SetColumnSpan(collectionView, 2);
            Content = grid;
        class NotesTemplate : DataTemplate
            public NotesTemplate() : base(LoadTemplate)
            static StackLayout LoadTemplate()
                var textLabel = new Label();
                textLabel.SetBinding(Label.TextProperty, nameof(NoteModel.Text));
                var frame = new Frame
                    VerticalOptions = LayoutOptions.Center,
                    Content = textLabel
                return new StackLayout
                    Children = { frame },
                    Padding = new Thickness(10)

Navigation in C#

当 view层有更改 会传递到 modelview
view层 MainPage.cs
在这里插入图片描述

MainPageViewModel.cs
在这里插入图片描述
例如我们选择goodbye 会看到selectNote .text中拿到了goodbye
在这里插入图片描述
在这里插入图片描述
然后将拿到的text 放入new 出来的DetailPage 并调用MainPage.navigation.pushAsync(new DetailPage(detailViewModel)) 将刚才的detailviewModel push到MainPage,MainPage相当于是一个后进先出的栈

var detailViewModel = new DetailPageViewModel{
    NoteText = SelectedNote.Text
await Application.Current.MainPage.Navigation.PushAsync(new DetailPage(detailViewModel));

同理当我们进入detailpage 界面点击pop view界面会检测到pop按钮被点击 并调用viewModel层相应的方法
如下图 viewModel层exit方法就是将MainPage 的栈顶page pop出

exitButton.SetBinding(Button.CommandProperty, nameof(DetailPageViewModel.ExitCommand));
                    Xamarin.Forms 是一个开放源代码 UI 框架。 通过 Xamarin.Forms,开发人员可从单个共享基本代码生成 Xamarin.Android、Xamarin.iOS 和 Windows 应用程序。
				
一、 前言 这十来天对Xamarin学习踩了很多的坑,说来也是一把心酸泪,下面为大家一 一道来,并提供这些天收集到的能用的实例源码,放在文末分享给大家,都是完整带包的解决方案可能会比较大(大多是过墙找到的,也有个仿新闻的app是国人写的)。 二、 后续更新预览 1、 Xamarin.forms环境搭建 2、 启动页(含图片加载) 3、 页面跳转 4、 Grid布局 5、 圆状头像
首先说到xamarin.Forms的安装,简直是坑+坑+坑,为什么呢,有些坑你完全意想不到,比如说你改名字后报错,比如说上份代码能运行,在这里就不能运行,具体先将坑说说吧 坑1 文件名,动不动就报什么大于256个字节,这样的错误,这是因为你没有将文件放在桌面,导致会报错 坑2 不能用中文命文件名,不能随便改动文件夹名字 坑3,有些文件显示说报错,你需要清理下解决方案 还有部署错误,一般通过...
---恢复内容开始--- Xamarin.Form怎么调用原生包 今天我想和大家分享的是有关Xamarin如何调用安卓的原生代码,下面的例子以大家可能会经常用到的微信WX方法的调用。 首先我们新建一个Xamarin.Android工程。 Xamarin.Form怎么调用原生包 今天我想和大家分享的是有关Xamarin如何调用安卓的原生代码,下面的例子以大家可能会经常用到的微信WX方法的调...
Xamarin.Forms是一个跨平台、支持原生UI工具包 ,允许开发者创建可以共享到跨Android、iOS、和Windows Phonep平台上的用户接口等这些网上很多介绍了。那么它的基本要求必须是Android4.0或以上、iOS6.1或以上、Windows Phone8只能用Visual Studio开发。 下面介绍Xamarin.Forms的Pages、Layouts、Views、Ce
  Phoneword这个项目是.net标准库项目,它包含所有的共享代码和共享UI。   Phoneword.Android这个项目包含Android特定的代码,是Android应用程序的入口点。   Phoneword.iOS -这个项目包含iOS特定的代码,是iOS应用程序的入口点。   Phoneword.UWP -这个项目包含通用Windows平台...
在使用Xamarin.Forms进行网页扫码的过程中,需要使用到ZXing.Net.Mobile库,该库是ZXing库的一个移动版,可以方便地实现生成和扫描二维码的功能。 首先,在Xamarin.Forms的代码中引用ZXing.Net.Mobile库,并在需要生成或扫描二维码的页面中添加ZXing控件。 使用ZXing库进行二维码生成时,需要设置二维码的内容和大小等参数,然后调用GenerateBarcode方法生成二维码图片,并将其作为Image控件的Source属性值。 使用ZXing库进行二维码扫描时,需要添加扫描完成后的处理逻辑,并在页面加载完成后调用StartScanning方法开始扫描。 在网页间扫描二维码的过程中,可以先将需要扫描的网址转换为二维码,然后在需要打开该页面的设备上扫描二维码即可快速跳转到对应网页。 总结来说,使用Xamarin.Forms进行网页间扫码,需要引用ZXing库实现二维码生成和扫描功能,并在页面中添加对应控件实现二维码的生成或扫描。该方法可以方便地实现快速跳转到对应网页的功能。