5 分钟上手 EclipseUI
- .NET 10.0 SDK 或更高版本
- Windows 10/11(目前仅支持 Windows)
git clone https://github.com/CeSun/EclipseUI.git
cd EclipseUIdotnet build EclipseUI.sln# 创建新的控制台应用
dotnet new console -n MyFirstApp
# 添加 EclipseUI 引用
cd MyFirstApp
dotnet add reference ../EclipseUI/src/Eclipse.Core
dotnet add reference ../EclipseUI/src/Eclipse.Controls
dotnet add reference ../EclipseUI/src/Eclipse.Skia
dotnet add reference ../EclipseUI/src/Eclipse.Windows创建 Components/HomePage.eui:
@using Eclipse.Controls
<StackLayout Spacing="16" Padding="20">
<Label Text="你好 EclipseUI! 🎉" FontSize="32" />
<Label Text="@_countText" FontSize="18" Color="#666666" />
<Button Text="点击我" OnClick="@OnButtonClick" />
</StackLayout>
@code {
private int _count = 0;
private string _countText => _count > 0
? $"点击次数: {_count}"
: "点击按钮开始计数";
private void OnButtonClick(object? sender, EventArgs e)
{
_count++;
StateHasChanged();
}
}修改 MyFirstApp.csproj,添加 EUI 文件支持:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net10.0-windows</TargetFramework>
<RootNamespace>MyFirstApp</RootNamespace>
</PropertyGroup>
<ItemGroup>
<!-- 引用 EclipseUI 项目 -->
<ProjectReference Include="..\EclipseUI\src\Eclipse.Core\Eclipse.Core.csproj" />
<ProjectReference Include="..\EclipseUI\src\Eclipse.Controls\Eclipse.Controls.csproj" />
<ProjectReference Include="..\EclipseUI\src\Eclipse.Skia\Eclipse.Skia.csproj" />
<ProjectReference Include="..\EclipseUI\src\Eclipse.Windows\Eclipse.Windows.csproj" />
<!-- 添加 EUI 文件作为 AdditionalFiles -->
<AdditionalFiles Include="Components\**\*.eui" />
<!-- 引用 Source Generator -->
<ProjectReference Include="..\EclipseUI\src\Eclipse.Generator\Eclipse.Generator.csproj"
OutputItemType="Analyzer"
ReferenceOutputAssembly="false" />
</ItemGroup>
</Project>修改 Program.cs:
using Eclipse.Core;
using Eclipse.Skia;
using Eclipse.Windows;
class Program
{
static void Main(string[] args)
{
// 创建应用
var app = AppBuilder.Create()
.UseSkiaRenderer()
.UseWindowsWindow()
.Build();
// 运行主页面
app.Run<HomePage>();
}
}dotnet runEUI 文件在编译时由 Source Generator 转换为 C# 代码:
HomePage.eui → HomePage.eui.g.cs → 编译到程序集
生成的代码示例:
// <auto-generated />
// Generated from HomePage.eui
#nullable enable
using System;
using Eclipse.Core;
using Eclipse.Core.Abstractions;
using Eclipse.Controls;
namespace MyFirstApp.Components
{
public partial class HomePage : ComponentBase
{
private int _count = 0;
private string _countText => _count > 0
? $"点击次数: {_count}"
: "点击按钮开始计数";
private void OnButtonClick(object? sender, EventArgs e)
{
_count++;
StateHasChanged();
}
public override void Build(IBuildContext context)
{
using (context.BeginComponent<StackLayout>(new ComponentId(1), out var __stacklayout_1))
{
__stacklayout_1.Spacing = 16;
__stacklayout_1.Padding = 20;
using (context.BeginChildContent())
{
using (context.BeginComponent<Label>(new ComponentId(2), out var __label_2))
{
__label_2.Text = "你好 EclipseUI! 🎉";
__label_2.FontSize = 32;
}
using (context.BeginComponent<Label>(new ComponentId(3), out var __label_3))
{
__label_3.Text = _countText?.ToString();
__label_3.FontSize = 18;
__label_3.Color = "#666666";
}
using (context.BeginComponent<Button>(new ComponentId(4), out var __button_4))
{
__button_4.Text = "点击我";
__button_4.OnClick += OnButtonClick;
}
}
}
}
}
}Generator 会根据目标属性类型自动转换字面量:
| EUI 写法 | 属性类型 | 生成代码 |
|---|---|---|
FontSize="24" |
double | FontSize = 24 |
IsChecked="true" |
bool | IsChecked = true |
TextAlignment="Center" |
TextAlignment | TextAlignment = TextAlignment.Center |
Color="#FF0000" |
Color | Color = Color.FromHex("#FF0000") |
Padding="16,8" |
Thickness | Padding = new Thickness(16, 8) |
生成的组件命名空间按以下规则推断:
@namespace指令(最高优先级)- MSBuild RootNamespace + 相对路径
- 默认值
Eclipse.Generated
示例:
项目: MyApp.csproj (<RootNamespace>MyApp</RootNamespace>)
文件: Components/Pages/HomePage.eui
生成命名空间: MyApp.Components.Pages
Generator 会报告编译时诊断:
| 诊断码 | 说明 |
|---|---|
| ECGEN001 | 组件生成失败 |
| ECGEN002 | Markup 解析错误 |
| ECGEN003 | 控件类型未找到(警告) |
项目包含一个完整的示例应用:
cd samples/SkiaDemo
dotnet run示例应用展示:
- ✅ 基础控件(Label、Button、TextInput)
- ✅ 布局控件(StackLayout、Grid、ScrollView)
- ✅ 交互控件(CheckBox)
- ✅ 图片显示(Image)
- ✅ Emoji 文本渲染
EclipseUI/
├── src/
│ ├── Eclipse.Core/ # 核心抽象层
│ │ ├── BuildContext # 组件构建上下文
│ │ ├── ComponentBase # 组件基类
│ │ └── Input/ # 输入系统
│ │
│ ├── Eclipse.Controls/ # UI 控件库
│ │ ├── Label # 文本显示
│ │ ├── Button # 按钮
│ │ ├── TextInput # 文本输入(支持光标、键盘)
│ │ ├── StackLayout # 堆叠布局
│ │ ├── Grid # 网格布局
│ │ └── ScrollView # 滚动视图
│ │
│ ├── Eclipse.Skia/ # SkiaSharp 渲染层
│ │ └── Text/ # 文本系统
│ │ ├── HarfBuzz # 文本塑形
│ │ └ EmojiDetector # Emoji 检测
│ │
│ ├── Eclipse.Generator/ # EUI Source Generator
│ │ └── EclipseSourceGenerator.cs
│ │
│ └── Eclipse.Windows/ # Windows 平台支持
│
├── samples/
│ └── Demo/ # 示例应用
│
├── tests/
│ └── Eclipse.Tests/ # 单元测试(137 个测试)
│
└── docs/
├── architecture.md # 架构设计
├── syntax.md # EUI 语法参考
└── getting-started.md # 快速开始(本文档)
组件是 EclipseUI 的基本构建单元。所有 UI 元素都继承自 ComponentBase:
public abstract class ComponentBase : IComponent
{
// 子元素集合
public ComponentCollection Children { get; }
// 脏标记(用于增量更新)
protected bool IsDirty { get; set; } = true;
// 构建 UI
public abstract void Build(IBuildContext context);
// 渲染
public abstract void Render(IDrawingContext context, Rect bounds);
// 触发重新渲染
protected void StateHasChanged();
}控件实现 Measure() 和 Arrange() 方法:
public class StackLayout : ComponentBase
{
public Size Measure(Size availableSize, IDrawingContext context);
public void Arrange(Rect finalBounds, IDrawingContext context);
}- Measure: 计算控件所需尺寸
- Arrange: 安排子元素位置
EclipseUI 提供完整的输入事件系统:
指针事件:
PointerPressed/PointerReleasedPointerMoved/PointerEntered/PointerExitedPointerWheelChangedTapped
键盘事件:
KeyDown/KeyUpTextInput
事件路由:
Bubble- 从源元素向上传播Tunnel- 从根元素向下传播Direct- 仅在源元素触发
阅读 EUI 语法参考 了解:
- 完整指令列表(@using, @namespace, @code, @inherits, @inject, @attribute)
- 强类型属性系统
- 复杂类型转换(Color, Thickness, Point 等)
- 控制流(@if, @foreach)
- 事件处理
阅读 架构设计 了解:
- SkiaSharp 渲染原理
- 文本塑形系统
- Source Generator 工作流程
- 跨平台架构设计
查看 samples/Demo 目录:
Components/HomePage.eui- 主页面Components/DemoControls.eui- 控件演示Components/DemoLayout.eui- 布局演示
EclipseUI 目前处于早期开发阶段,优先支持 Windows 平台。未来计划支持:
- macOS
- Linux
- Android
- iOS
| 特性 | Razor | EUI |
|---|---|---|
| 目标 | Web | 跨平台 UI |
| 渲染 | HTML | SkiaSharp |
| 运行时 | Blazor Server/WebAssembly | 原生窗口 |
| 类型系统 | 运行时动态 | 编译时强类型 |
<Image Source="assets/photo.png" Stretch="Uniform" />图片路径相对于应用目录。支持格式:PNG, JPEG, WEBP, GIF, BMP。
继承 InteractiveControl 或 ComponentBase:
public class MyControl : InteractiveControl
{
public string? MyProperty { get; set; }
public override Size Measure(Size availableSize, IDrawingContext context)
{
return new Size(100, 50);
}
public override void Render(IDrawingContext context, Rect bounds)
{
context.DrawRectangle(bounds, "#FF0000");
}
}确保使用 @using 引入命名空间:
@using Eclipse.Controls
@using MyApp.CustomControls <!-- 自定义控件 -->
<MyControl ... />如果仍有警告(ECGEN003),检查类型名称是否正确。
欢迎提交 Issue 和 Pull Request!
贡献指南:
- Fork 项目
- 创建功能分支 (
git checkout -b feature/amazing-feature) - 提交更改 (
git commit -m 'Add amazing feature') - 推送分支 (
git push origin feature/amazing-feature) - 提交 Pull Request
MIT License - 自由使用、修改和分发。