MAUI
简介
什么是MAUI
.NET 多平台应用 UI (.NET MAUI) 是一个跨平台框架,用于使用 C# 和 XAML 创建本机移动和桌面应用。 使用 .NET MAUI,可从单个共享代码库开发可在 Android、iOS、macOS 和 Windows 上运行的应用。
环境准备
确保你的Vs安装了这个组件
创建项目
选择MAUI应用创建,设置你的项目名字
启动项目
选择你的启动方式:
Windows启动
如果要在Windows中启动将会出现以下提示:为Windows启用开发人员模式,你需要点击链接然后启用开发人员模式。
Android启动
选择启动然后接受许可协议,然后创建一个模拟器
需要在Windows功能中启用以下功能加速安卓模拟器。确保在Android设备管理器中创建的虚拟设备是基于x86-64或基于x86的系统映像。如果使用基于ARM的系统映像,虚拟设备将无法加速并且运行缓慢。
创建完模拟器选择启动,第一次部署项目比较慢,后面部署会对比上一次部署的差异,然后编译差异的内容而不是所有内容,然后部署到模拟器中
项目结构
Visual Studio 创建 .NET MAUI 项目时,将生成四个重要的代码文件。 可以在 Visual Studio 的“解决方案资源管理器”窗格中看到这些文件:
MauiProgram.cs
这是启动应用的代码文件。 此文件中的代码充当应用的跨平台入口点,用于配置和启动应用。 模板启动代码指向 App.xaml 文件定义的 App 类。更细节的一点是其实这个文件不是最开始的入口,最开始的入口实在Platforms文件夹中实际平台的启动应用代码文件,比如安卓:
可以看到实际代码是指到MauiProgram.cs这个文件的,虽然但是一般只需要关注MauiProgram就行了,如果不是特殊情况下
public class MainApplication : MauiApplication
{
public MainApplication(IntPtr handle, JniHandleOwnership ownership)
: base(handle, ownership)
{
}
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
}
App.xaml 和 App.xaml.cs
为了简单起见,这两个文件称为单个文件。 所有 XAML 文件通常都包含两个文件,即 .xaml 文件本身,以及一个相应的代码文件,该文件是“解决方案资源管理器”中的 .xaml 文件的子项。 .xaml 文件包含 XAML 标记,代码文件包含用户创建的用于与 XAML 标记交互的代码。
App.xaml 文件包含应用范围的 XAML 资源,例如颜色、样式或模板。 App.xaml.cs 文件通常包含用于实例化 Shell 应用程序的代码。 在此项目中,它指向 AppShell 类。
AppShell.xaml 和 AppShell.xaml.cs
此文件定义 AppShell 类,该类用于定义应用的视觉层次结构。
MainPage.xaml 和 MainPage.xaml.cs
这是应用显示的启动页。 MainPage.xaml 文件定义页面的 UI(用户界面)。 MainPage.xaml.cs 包含 XAML 的代码隐藏,如按钮单击事件的代码。
代码编写
创建模型
创建Mods文件夹,创建以下两个类Contact.cs,ContactReposiroty.cs
namespace Contacts.Maui.Mods
{
class Contact
{
public int ContactId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Address { get; set; }
public Contact(int contactId, string name, string email, string phone,string adddress)
{
Name = name;
Email = email;
ContactId = contactId;
Phone = phone;
Address = adddress;
}
public Contact() { }
}
}
namespace Contacts.Maui.Mods
{
class ContactRepository
{
public static List<Contact> _contacts = new List<Contact>()
{
new Contact(1,"John Doe","JohnDoe@gmail.com","416-800-8000","New York"),
new Contact(2,"Jane Doe","JaneDoe@gmail.com","","New York"),
new Contact(3,"Tom Hanks","TomHanks@gmail.com","","New York"),
new Contact(4,"Frank Liu","FrankLiu@gmail.com","","New York"),
};
public static List<Contact> GetContacts() => _contacts;
public static Contact GetContactById(int contactId)
{
return _contacts.FirstOrDefault(x => x.ContactId == contactId);
}
public static void UpdateContact(int contactId,Contact contact)
{
if(contact.ContactId!= contact.ContactId)
{
return;
}
var oldContact = GetContactById(contactId);
if(oldContact != null)
{
oldContact = contact;
}
}
public static void CreateContact(Contact contact)
{
var maxId = _contacts.Max(x => x.ContactId);
contact.ContactId = maxId+1;
_contacts.Add(contact);
}
public static void DeleteContact(int contactId)
{
var contact = _contacts.FirstOrDefault( x => x.ContactId == contactId);
if (contact == null)
{
return;
}
_contacts.Remove(contact);
}
public static List<Contact> SearchContacts(string filterText)
{
var contacts = _contacts.Where(x =>!string.IsNullOrWhiteSpace(x.Name) && x.Name.StartsWith(filterText, StringComparison.OrdinalIgnoreCase)).ToList();
if(contacts == null || contacts.Count <= 0)
{
contacts = _contacts.Where(x => !string.IsNullOrWhiteSpace(x.Email) && x.Email.StartsWith(filterText, StringComparison.OrdinalIgnoreCase)).ToList();
}
else
{
return contacts;
}
if (contacts == null || contacts.Count <= 0)
{
contacts = _contacts.Where(x => !string.IsNullOrWhiteSpace(x.Phone) && x.Phone.StartsWith(filterText, StringComparison.OrdinalIgnoreCase)).ToList();
}
else
{
return contacts;
}
if (contacts == null || contacts.Count <= 0)
{
contacts = _contacts.Where(x => !string.IsNullOrWhiteSpace(x.Address) && x.Address.StartsWith(filterText, StringComparison.OrdinalIgnoreCase)).ToList();
}
else
{
return contacts;
}
return contacts;
}
}
}
创建页面
这个Demo需要用到一个工具包CommunityToolkit.Maui,通过nuget管理安装
安装完以后需要在MauiProgram.cs中引用
builder.UseMauiCommunityToolkit();
新建页面之前新建文件夹Views存放视图页面
创建组件视图,先新建一个Controls文件夹
创建一个组件ContactControl.xaml,选择ContentView
ContactControl.xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Contacts.Maui.Views.Controls.ContactControl"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit">
<!--垂直布局
Spacing每个组件的间隔
-->
<VerticalStackLayout Spacing="10" Margin="20,20,20,0">
<Frame Padding="10,0,10,0">
<HorizontalStackLayout>
<Label Text="Name" VerticalOptions="Center" WidthRequest="60"></Label>
<Entry x:Name="entryName" VerticalOptions="Center">
<Entry.Behaviors>
<!--toolkit工具包的文本验证Flags触发方式-->
<toolkit:TextValidationBehavior
x:Name="nameValidator"
Flags="ValidateOnAttaching,ValidateOnValueChanged"
MinimumLength="1"/>
</Entry.Behaviors>
</Entry>
</HorizontalStackLayout>
</Frame>
<Frame Padding="10,0,10,0">
<HorizontalStackLayout>
<Label Text="Email" VerticalOptions="Center" WidthRequest="60"></Label>
<Entry x:Name="entryEmail" VerticalOptions="Center">
<Entry.Behaviors>
<!--多重验证-->
<toolkit:MultiValidationBehavior
x:Name="emailValidator"
Flags="ValidateOnAttaching,ValidateOnValueChanged">
<toolkit:TextValidationBehavior
Flags="ValidateOnAttaching,ValidateOnValueChanged"
MinimumLength="1"
toolkit:MultiValidationBehavior.Error="Email is required."/>
<toolkit:EmailValidationBehavior
Flags="ValidateOnAttaching,ValidateOnValueChanged"
MinimumLength="1"
toolkit:MultiValidationBehavior.Error="Email format is invalid."/>
</toolkit:MultiValidationBehavior>
</Entry.Behaviors>
</Entry>
</HorizontalStackLayout>
</Frame>
<Frame Padding="10,0,10,0">
<HorizontalStackLayout>
<Label Text="Phone" VerticalOptions="Center" WidthRequest="60"></Label>
<Entry x:Name="entryPhone" VerticalOptions="Center"></Entry>
</HorizontalStackLayout>
</Frame>
<Frame Padding="10,0,10,0">
<HorizontalStackLayout>
<Label Text="Address" VerticalOptions="Center" WidthRequest="60"></Label>
<Entry x:Name="entryAddress" VerticalOptions="Center"></Entry>
</HorizontalStackLayout>
</Frame>
<Button x:Name="btnSave" Text="Save" Clicked="btnSave_Clicked"></Button>
<Button x:Name="btnCancel" Text="Cancel" Clicked="btnCancel_Clicked"></Button>
</VerticalStackLayout>
</ContentView>
ContactControl.xmal.cs:
namespace Contacts.Maui.Views.Controls;
public partial class ContactControl : ContentView
{
public ContactControl()
{
InitializeComponent();
}
//类似于vue中的defindEmits
public event EventHandler<string> OnError;
public event EventHandler<EventArgs> OnSave;
public event EventHandler<EventArgs> OnCancel;
public string Name { get { return entryName.Text; } set { entryName.Text = value; } }
public string Email { get { return entryEmail.Text; } set { entryEmail.Text = value; } }
public string Address { get { return entryAddress.Text; } set { entryAddress.Text = value; } }
public string Phone { get { return entryPhone.Text; } set { entryPhone.Text = value; } }
private void btnSave_Clicked(object sender, EventArgs e)
{
if (nameValidator.IsNotValid)
{
OnError?.Invoke(sender,"Name is required.");
return;
}
if (emailValidator.IsNotValid)
{
var message = "";
foreach (var error in emailValidator.Errors)
{
message += error + "\n";
}
OnError?.Invoke(sender,message);
return;
}
OnSave?.Invoke(sender,e);
}
private void btnCancel_Clicked(object sender, EventArgs e)
{
OnCancel?.Invoke(sender,e);
}
}
新建AddContactPage,EditContactPage,ContactsPage页面,选择ContentPage
最终视图文件:
最终效果:
toolkit地址:github.com/CommunityTo…