Files
LanMountainDesktop/docs/01-AirApp开发/01-快速开始/02-创建第一个轻应用.md

531 lines
14 KiB
Markdown
Raw Normal View History

2026-08-11 23:03:55 +08:00
# 创建第一个轻应用
2026-06-08 12:18:58 +08:00
2026-08-11 23:03:55 +08:00
通过这个教程,你将在 15 分钟内创建一个简单但功能完整的轻应用。
2026-06-08 12:18:58 +08:00
## 学习目标
2026-08-11 23:03:55 +08:00
- ✅ 使用模板创建轻应用项目
- ✅ 实现轻应用入口类
2026-06-08 12:18:58 +08:00
- ✅ 创建一个简单的桌面组件
- ✅ 注册组件到宿主
2026-08-11 23:03:55 +08:00
- ✅ 运行和测试轻应用
2026-06-08 12:18:58 +08:00
## 前置准备
确保你已经:
- ✅ 安装了 .NET 10 SDK
2026-08-11 23:03:55 +08:00
- ✅ 安装了轻应用模板(参考 [环境准备](01-环境准备.md)
2026-06-08 12:18:58 +08:00
- ✅ 有一个支持 C# 的 IDE
## 步骤 1: 创建项目
### 使用模板创建
```powershell
2026-08-11 23:03:55 +08:00
# 创建新轻应用项目
dotnet new lmd-airapp -n HelloWorldAirApp
2026-06-08 12:18:58 +08:00
# 进入项目目录
2026-08-11 23:03:55 +08:00
cd HelloWorldAirApp
2026-06-08 12:18:58 +08:00
# 还原依赖
dotnet restore
```
### 项目结构预览
```
2026-08-11 23:03:55 +08:00
HelloWorldAirApp/
├── HelloWorldAirApp.csproj # 项目文件
├── AirApp.cs # 轻应用入口(我们要修改这个)
├── airapp.json # 轻应用清单(我们要修改这个)
2026-06-08 12:18:58 +08:00
├── Components/
│ └── SampleComponent.cs # 示例组件(我们要修改这个)
├── Views/
│ └── SampleComponentView.axaml # 组件视图(我们要修改这个)
├── ViewModels/
│ └── SampleComponentViewModel.cs
├── Assets/
2026-08-11 23:03:55 +08:00
│ └── icon.png # 轻应用图标
2026-06-08 12:18:58 +08:00
└── Settings/
2026-08-11 23:03:55 +08:00
└── AirAppSettingsPage.axaml # 设置页
2026-06-08 12:18:58 +08:00
```
2026-08-11 23:03:55 +08:00
## 步骤 2: 配置轻应用清单
2026-06-08 12:18:58 +08:00
2026-08-11 23:03:55 +08:00
编辑 `airapp.json`,修改基本信息:
2026-06-08 12:18:58 +08:00
```json
{
"Id": "com.example.helloworldplugin",
2026-08-11 23:03:55 +08:00
"Name": "Hello World AirApp",
2026-06-08 12:18:58 +08:00
"Version": "1.0.0",
"Author": "Your Name",
"Description": "My first LanMountainDesktop plugin - displays a greeting",
"MinHostVersion": "1.0.0",
"SdkVersion": "5.0.0",
"Dependencies": [],
"Permissions": [],
"Icon": "Assets/icon.png",
"Homepage": "https://github.com/yourusername/helloworldplugin"
}
```
### 字段说明
2026-08-11 23:03:55 +08:00
- **Id**: 轻应用唯一标识符,建议使用反向域名格式
- **Name**: 用户看到的轻应用名称
- **Version**: 轻应用版本号(语义化版本)
2026-06-08 12:18:58 +08:00
- **MinHostVersion**: 最低支持的宿主版本
- **SdkVersion**: 使用的 SDK 版本
2026-08-11 23:03:55 +08:00
## 步骤 3: 实现轻应用入口
2026-06-08 12:18:58 +08:00
2026-08-11 23:03:55 +08:00
编辑 `AirApp.cs`
2026-06-08 12:18:58 +08:00
```csharp
2026-08-11 23:03:55 +08:00
using LanMountainDesktop.AirAppSdk;
2026-06-08 12:18:58 +08:00
using LanMountainDesktop.Shared.Contracts;
2026-08-11 23:03:55 +08:00
using HelloWorldAirApp.Components;
using HelloWorldAirApp.Views;
using HelloWorldAirApp.ViewModels;
2026-06-08 12:18:58 +08:00
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
2026-08-11 23:03:55 +08:00
namespace HelloWorldAirApp;
2026-06-08 12:18:58 +08:00
/// <summary>
2026-08-11 23:03:55 +08:00
/// Hello World 轻应用入口
2026-06-08 12:18:58 +08:00
/// </summary>
2026-08-11 23:03:55 +08:00
public class AirApp : IAirApp
2026-06-08 12:18:58 +08:00
{
public string Id => "com.example.helloworldplugin";
2026-08-11 23:03:55 +08:00
public string Name => "Hello World AirApp";
2026-06-08 12:18:58 +08:00
public string Version => "1.0.0";
2026-08-11 23:03:55 +08:00
private IAirAppRuntimeContext? _context;
2026-06-08 12:18:58 +08:00
/// <summary>
2026-08-11 23:03:55 +08:00
/// 轻应用初始化
2026-06-08 12:18:58 +08:00
/// </summary>
2026-08-11 23:03:55 +08:00
public async Task InitializeAsync(IAirAppRuntimeContext context)
2026-06-08 12:18:58 +08:00
{
_context = context;
// 记录日志
2026-08-11 23:03:55 +08:00
context.Logger.LogInformation("Hello World AirApp is initializing...");
2026-06-08 12:18:58 +08:00
// 获取组件注册表
var componentRegistry = context.Services
.GetService<IComponentRegistry>();
if (componentRegistry != null)
{
// 注册 Hello World 组件
componentRegistry.RegisterComponent<HelloWorldComponent>(
componentFactory: () => new HelloWorldComponent(),
viewFactory: (component) => new HelloWorldComponentView
{
DataContext = new HelloWorldComponentViewModel(
(HelloWorldComponent)component
)
}
);
context.Logger.LogInformation(
"HelloWorldComponent registered successfully"
);
}
// 异步操作示例(如果需要)
await Task.CompletedTask;
}
/// <summary>
2026-08-11 23:03:55 +08:00
/// 轻应用关闭
2026-06-08 12:18:58 +08:00
/// </summary>
public async Task ShutdownAsync()
{
_context?.Logger.LogInformation(
2026-08-11 23:03:55 +08:00
"Hello World AirApp is shutting down..."
2026-06-08 12:18:58 +08:00
);
// 清理资源(如果有)
await Task.CompletedTask;
}
}
```
### 代码说明
2026-08-11 23:03:55 +08:00
1. **实现 IAirApp 接口** - 定义轻应用的基本信息和生命周期
2. **InitializeAsync** - 轻应用加载时调用,注册组件和服务
3. **ShutdownAsync** - 轻应用卸载时调用,清理资源
2026-06-08 12:18:58 +08:00
4. **日志记录** - 使用 `context.Logger` 记录日志
## 步骤 4: 创建组件类
编辑 `Components/SampleComponent.cs`,重命名为 `HelloWorldComponent.cs`
```csharp
2026-08-11 23:03:55 +08:00
using LanMountainDesktop.AirAppSdk.Components;
2026-06-08 12:18:58 +08:00
using LanMountainDesktop.Shared.Contracts.Components;
using System.ComponentModel;
2026-08-11 23:03:55 +08:00
namespace HelloWorldAirApp.Components;
2026-06-08 12:18:58 +08:00
/// <summary>
/// Hello World 桌面组件
/// </summary>
[Component(
Id = "com.example.helloworldplugin.helloworld",
Name = "Hello World",
Description = "Displays a friendly greeting message",
Category = "Demo",
2026-08-11 23:03:55 +08:00
Icon = "avares://HelloWorldAirApp/Assets/icon.png"
2026-06-08 12:18:58 +08:00
)]
public class HelloWorldComponent : ComponentBase
{
public override string Id => "com.example.helloworldplugin.helloworld";
public override string Name => "Hello World";
private string _greeting = "Hello, World!";
private int _clickCount = 0;
/// <summary>
/// 问候语
/// </summary>
public string Greeting
{
get => _greeting;
set => SetProperty(ref _greeting, value);
}
/// <summary>
/// 点击次数
/// </summary>
public int ClickCount
{
get => _clickCount;
set => SetProperty(ref _clickCount, value);
}
/// <summary>
/// 组件初始化
/// </summary>
public override Task InitializeAsync()
{
// 从设置加载问候语
Greeting = Settings.GetValue("Greeting", "Hello, World!");
ClickCount = Settings.GetValue("ClickCount", 0);
Logger.LogInformation("HelloWorldComponent initialized");
return Task.CompletedTask;
}
/// <summary>
/// 组件更新(定时调用)
/// </summary>
public override Task UpdateAsync()
{
// 这里可以更新组件数据
// 例如:从 API 获取数据、更新时间等
return Task.CompletedTask;
}
/// <summary>
/// 增加点击次数
/// </summary>
public void IncrementClickCount()
{
ClickCount++;
Settings.SetValue("ClickCount", ClickCount);
}
}
```
### 组件说明
- **ComponentBase** - 所有组件的基类,提供基础功能
- **属性通知** - 使用 `SetProperty` 自动触发 UI 更新
- **设置持久化** - 使用 `Settings` 保存和读取配置
- **InitializeAsync** - 组件创建时调用
- **UpdateAsync** - 定时调用(默认 1 秒),用于更新数据
## 步骤 5: 创建组件视图
编辑 `Views/SampleComponentView.axaml`,重命名为 `HelloWorldComponentView.axaml`
```xml
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
2026-08-11 23:03:55 +08:00
xmlns:vm="using:HelloWorldAirApp.ViewModels"
x:Class="HelloWorldAirApp.Views.HelloWorldComponentView"
2026-06-08 12:18:58 +08:00
x:DataType="vm:HelloWorldComponentViewModel">
<!-- 组件容器 -->
<Border Background="{DynamicResource CardBackgroundBrush}"
CornerRadius="{DynamicResource DesignCornerRadiusComponent}"
Padding="20"
BorderBrush="{DynamicResource CardBorderBrush}"
BorderThickness="1">
<StackPanel Spacing="12">
<!-- 标题 -->
<TextBlock Text="{Binding Component.Name}"
FontSize="18"
FontWeight="Bold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
<!-- 问候语 -->
<TextBlock Text="{Binding Component.Greeting}"
FontSize="16"
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
TextWrapping="Wrap" />
<!-- 点击次数 -->
<TextBlock Foreground="{DynamicResource TextFillColorTertiaryBrush}">
<Run Text="Clicks: " />
<Run Text="{Binding Component.ClickCount}" FontWeight="Bold" />
</TextBlock>
<!-- 按钮 -->
<Button Content="Click Me!"
Command="{Binding ClickCommand}"
HorizontalAlignment="Stretch"
Padding="12,8" />
</StackPanel>
</Border>
</UserControl>
```
编辑对应的代码后台 `HelloWorldComponentView.axaml.cs`
```csharp
using Avalonia.Controls;
2026-08-11 23:03:55 +08:00
namespace HelloWorldAirApp.Views;
2026-06-08 12:18:58 +08:00
public partial class HelloWorldComponentView : UserControl
{
public HelloWorldComponentView()
{
InitializeComponent();
}
}
```
### 视图说明
- **动态资源** - 使用 `{DynamicResource}` 适配主题
- **圆角规范** - 使用 `DesignCornerRadiusComponent` 保持一致性
- **数据绑定** - 使用 `{Binding}` 绑定到 ViewModel
- **响应式布局** - 使用 `StackPanel` 自动布局
## 步骤 6: 创建视图模型
编辑 `ViewModels/SampleComponentViewModel.cs`,重命名为 `HelloWorldComponentViewModel.cs`
```csharp
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
2026-08-11 23:03:55 +08:00
using HelloWorldAirApp.Components;
2026-06-08 12:18:58 +08:00
2026-08-11 23:03:55 +08:00
namespace HelloWorldAirApp.ViewModels;
2026-06-08 12:18:58 +08:00
/// <summary>
/// Hello World 组件视图模型
/// </summary>
public partial class HelloWorldComponentViewModel : ObservableObject
{
[ObservableProperty]
private HelloWorldComponent _component;
public HelloWorldComponentViewModel(HelloWorldComponent component)
{
_component = component;
}
/// <summary>
/// 点击按钮命令
/// </summary>
[RelayCommand]
private void Click()
{
Component.IncrementClickCount();
// 更新问候语
var greetings = new[]
{
"Hello, World!",
"你好,世界!",
"Bonjour le monde!",
"Hola, Mundo!",
"Привет, мир!",
"こんにちは、世界!"
};
var index = Component.ClickCount % greetings.Length;
Component.Greeting = greetings[index];
// 保存问候语
Component.Settings.SetValue("Greeting", Component.Greeting);
}
}
```
### ViewModel 说明
- **ObservableObject** - MVVM Toolkit 基类,提供属性通知
- **[ObservableProperty]** - 自动生成属性和通知代码
- **[RelayCommand]** - 自动生成命令
- **业务逻辑** - 处理用户交互和数据更新
2026-08-11 23:03:55 +08:00
## 步骤 7: 构建轻应用
2026-06-08 12:18:58 +08:00
```powershell
# 构建项目
dotnet build -c Release
# 查看输出
dir bin\Release\net10.0\
```
输出目录应包含:
2026-08-11 23:03:55 +08:00
- `HelloWorldAirApp.dll` - 主程序集
- `airapp.json` - 轻应用清单
2026-06-08 12:18:58 +08:00
- `Assets/` - 资源文件
- 依赖的 DLL 文件
## 步骤 8: 安装和测试
2026-08-11 23:03:55 +08:00
### 方法 1: 复制到轻应用目录
2026-06-08 12:18:58 +08:00
```powershell
2026-08-11 23:03:55 +08:00
# 创建轻应用目录
$pluginDir = "$env:LOCALAPPDATA\LanMountainDesktop\plugins\HelloWorldAirApp"
2026-06-08 12:18:58 +08:00
New-Item -ItemType Directory -Path $pluginDir -Force
# 复制文件
Copy-Item -Path "bin\Release\net10.0\*" -Destination $pluginDir -Recurse -Force
# 启动宿主应用
# (从开始菜单或安装目录启动)
```
### 方法 2: 使用符号链接(开发模式)
```powershell
# 需要管理员权限
2026-08-11 23:03:55 +08:00
$pluginDir = "$env:LOCALAPPDATA\LanMountainDesktop\plugins\HelloWorldAirApp"
2026-06-08 12:18:58 +08:00
$buildDir = "$(pwd)\bin\Release\net10.0"
New-Item -ItemType SymbolicLink -Path $pluginDir -Target $buildDir -Force
```
2026-08-11 23:03:55 +08:00
### 验证轻应用加载
2026-06-08 12:18:58 +08:00
1. 启动阑山桌面
2. 查看日志文件:
```powershell
Get-Content "$env:LOCALAPPDATA\LanMountainDesktop\logs\latest.log" -Tail 50
```
3. 应该看到类似输出:
```
2026-08-11 23:03:55 +08:00
[INFO] Hello World AirApp is initializing...
2026-06-08 12:18:58 +08:00
[INFO] HelloWorldComponent registered successfully
```
### 添加组件到桌面
1. 右键点击桌面空白处
2. 选择"添加组件"
3. 找到"Hello World"组件
4. 点击添加
5. 组件应该出现在桌面上
### 测试功能
1. 点击"Click Me!"按钮
2. 观察点击次数增加
3. 观察问候语在不同语言间切换
4. 重启应用,验证设置持久化
2026-08-11 23:03:55 +08:00
## 步骤 9: 调试轻应用
2026-06-08 12:18:58 +08:00
### 附加调试器
1. 启动阑山桌面应用
2. 在 Visual Studio 中:
- 选择"调试" → "附加到进程"
- 找到 `LanMountainDesktop.exe`
- 点击"附加"
2026-08-11 23:03:55 +08:00
3. 在轻应用代码中设置断点
2026-06-08 12:18:58 +08:00
4. 触发相应功能(如点击按钮)
### 查看日志
```powershell
# 实时查看日志
Get-Content "$env:LOCALAPPDATA\LanMountainDesktop\logs\latest.log" -Wait -Tail 50
```
### 常见问题
2026-08-11 23:03:55 +08:00
#### 轻应用没有加载
2026-06-08 12:18:58 +08:00
**检查清单**:
2026-08-11 23:03:55 +08:00
1. `airapp.json` 存在且格式正确
2. 轻应用 DLL 文件存在
2026-06-08 12:18:58 +08:00
3. 查看日志中的错误信息
2026-08-11 23:03:55 +08:00
4. 确认轻应用 ID 唯一
2026-06-08 12:18:58 +08:00
#### 组件没有显示
**检查清单**:
1. 组件已正确注册
2. 组件 ID 唯一
3. 视图文件正确编译为 AvaloniaResource
4. DataContext 正确设置
#### 按钮点击没有响应
**检查清单**:
1. Command 绑定正确
2. ViewModel 方法存在
3. 查看日志中的异常信息
## 下一步
2026-08-11 23:03:55 +08:00
恭喜!你已经创建了第一个轻应用。接下来可以:
2026-06-08 12:18:58 +08:00
2026-08-11 23:03:55 +08:00
- [轻应用生命周期](../02-核心概念/01-轻应用生命周期.md) - 深入理解轻应用运行机制
2026-06-08 12:18:58 +08:00
- [组件系统详解](../02-核心概念/02-组件系统.md) - 学习更多组件功能
- [设置系统](../02-核心概念/03-设置系统.md) - 添加设置页面
- [实战案例](../04-实战案例/01-天气组件.md) - 学习完整的实战案例
## 完整代码仓库
本教程的完整代码可以在以下位置找到:
2026-08-11 23:03:55 +08:00
- GitHub: https://github.com/HelloWRC/LanMountainDesktop.SampleAirApp
2026-06-08 12:18:58 +08:00
## 小结
在这个教程中,你学会了:
2026-08-11 23:03:55 +08:00
- ✅ 使用模板创建轻应用项目
- ✅ 配置轻应用清单
- ✅ 实现轻应用入口类
2026-06-08 12:18:58 +08:00
- ✅ 创建桌面组件(模型、视图、视图模型)
- ✅ 注册组件到宿主
- ✅ 使用设置系统持久化数据
2026-08-11 23:03:55 +08:00
- ✅ 构建、安装和测试轻应用
- ✅ 调试轻应用代码
2026-06-08 12:18:58 +08:00
2026-08-11 23:03:55 +08:00
这是一个完整但简单的轻应用,展示了轻应用开发的基本流程。在实际项目中,你可以添加更多功能,如网络请求、定时任务、复杂 UI 等。