导读:本期聚焦于仓本创作的《C# MAUI怎么使用C# Markup编写UI?MAUI C# UI完整教程》,敬请观看详情。还在用XAML写MAUI界面吗?C# Markup提供了一种纯代码构建UI的方式,让你告别XML标签的繁琐,直接用强类型的C#语法声明界面。本文将详细介绍C# Markup的安装配置、核心API用法、常用控件示例、数据绑定实现方式,以及与XAML方案的性能和开发体验对比。通过搭建一个完整示例,你会掌握如何用链式调用快速搭建页面布局,如何处理事件绑定和样式设置,还会了解C# Markup在热重载、可读性和团队协作方面的优势与不足。无论你是刚接触MAUI的新手,还是想优化XAML开发流程的老手,这篇教程都能帮你快速上手纯C# UI开发。

C# Markup是.NET MAUI官方支持的一种UI编写方式,它允许开发者完全用C#代码来声明界面,而不需要写一行XAML。对于熟悉C#但不习惯XAML语法的开发者来说,这条路径上手更快,代码提示和重构支持也更完善。本文将从环境搭建开始,一步步带你掌握C# Markup的核心用法。

C# MAUI怎么使用C# Markup编写UI?MAUI C# UI完整教程

一、C# Markup是什么,为什么值得尝试

传统的MAUI应用默认使用XAML来描述界面,XAML本质上是一种XML方言,通过标签和属性的组合来声明控件树。这种方式虽然结构清晰,但存在一些固有的痛点:属性名没有编译期检查、重构控件名需要手动同步、复杂的绑定表达式调试困难、代码与界面分离导致频繁切换文件等。

C# Markup的出现就是为了解决这些问题。它通过一组扩展方法,让C#代码能够以声明式的风格描述UI结构。由于整个界面都是C#代码,编译器可以在构建阶段发现拼写错误和类型不匹配,智能提示也能覆盖所有属性和方法。此外,界面逻辑和界面结构在同一个文件中,来回切换的次数大大减少。

从底层实现来看,C# Markup本质上还是构建了和XAML相同的控件对象树,运行时行为完全一致,只是描述方式从XML换成了C#的链式调用。这意味着XAML能实现的布局、绑定、样式,C# Markup都能做到。

二、环境搭建与基础示例

使用C# Markup需要先安装官方的NuGet包。在创建好MAUI项目后,通过命令行或者Visual Studio的包管理器安装CommunityToolkit.Maui.Markup包:

dotnet add package CommunityToolkit.Maui.Markup

安装完成后,还需要在MauiApp.CreateBuilder中注册Markup的支持服务。打开MauiProgram.cs文件,添加如下代码:

using CommunityToolkit.Maui.Markup;

namespace MauiMarkupDemo;

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .UseMauiCommunityToolkitMarkup(); // 注册Markup服务
        return builder.Build();
    }
}

接下来创建一个纯C#的页面。在项目中新建一个类MainPage,继承自ContentPage,然后在构造函数中用C# Markup声明界面:

using CommunityToolkit.Maui.Markup;
using Microsoft.Maui.Controls;

namespace MauiMarkupDemo;

public class MainPage : ContentPage
{
    public MainPage()
    {
        Content = new VerticalStackLayout
        {
            Spacing = 20,
            Padding = 30,
            Children =
            {
                new Label
                {
                    Text = "Hello, C# Markup!",
                    FontSize = 28,
                    FontAttributes = FontAttributes.Bold
                },
                new Entry
                {
                    Placeholder = "请输入内容"
                },
                new Button
                {
                    Text = "点击我"
                }.Invoke(button => button.Clicked += OnButtonClicked)
            }
        };
    }

    private void OnButtonClicked(object? sender, EventArgs e)
    {
        DisplayAlert("提示", "按钮被点击了", "确定");
    }
}

最后别忘了修改App.xaml.cs中的逻辑,让应用启动时加载这个页面。把MainPage属性改为new MainPage()即可。运行程序,一个简单的界面就完成了,整个过程没有触碰任何XAML文件。

三、核心API与常用控件用法详解

C# Markup的核心是一系列扩展方法,掌握它们可以大幅提升代码的简洁度。最常用的是各类属性设置扩展,比如Text()FontSize()TextColor()等,它们通过链式调用避免初始化器写法中的冗长代码。

new Label()
    .Text("用户名")
    .Font(size: 16, bold: true)
    .TextColor(Colors.DimGray)
    .Margin(0, 0, 0, 8);

除了属性设置,布局类的扩展方法也很实用。FillExpand()对应布局选项LayoutOptions.FillAndExpand,可以简化水平或垂直方向的排布设置:

new Grid
{
    ColumnDefinitions = Columns.Define(Star, Star, Star),
    RowDefinitions = Rows.Define(Auto, Star),
    Children =
    {
        new Label().Text("第一列").Row(0).Column(0),
        new Label().Text("第二列").Row(0).Column(1),
        new Entry().Row(1).ColumnSpan(3).FillExpand()
    }
};

上面的代码中,Columns.DefineRows.Define用简洁的语法定义网格结构,Row()Column()方法指定子元素的位置,ColumnSpan()处理跨列。这些辅助方法让Grid布局的代码量比初始化器写法减少了一半以上。

事件绑定方面,除了前面用到的Invoke,Markup还提供了更直接的方式。以按钮点击为例:

new Button()
    .Text("提交")
    .Invoke(button => button.Clicked += async (s, e) =>
    {
        await DisplayAlert("提示", "提交成功", "确定");
    });

四、数据绑定与MVVM模式的配合

C# Markup对MVVM模式的支持同样完善。虽然没有了XAML中的Binding标记扩展,但可以用Bind()方法实现同样的效果。首先定义一个简单的ViewModel:

public class CounterViewModel : INotifyPropertyChanged
{
    private int count;
    public int Count
    {
        get => count;
        set
        {
            count = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Count)));
        }
    }

    public Command IncrementCommand { get; }

    public CounterViewModel()
    {
        IncrementCommand = new Command(() => Count++);
    }

    public event PropertyChangedEventHandler? PropertyChanged;
}

然后在页面中通过Bind()方法建立视图与ViewModel的关联:

public class CounterPage : ContentPage
{
    public CounterPage()
    {
        var vm = new CounterViewModel();
        BindingContext = vm;

        Content = new VerticalStackLayout
        {
            Padding = 30,
            Spacing = 15,
            Children =
            {
                new Label()
                    .Bind(Label.TextProperty, nameof(CounterViewModel.Count),
                          convert: (int count) => $"当前计数:{count}"),
                new Button()
                    .Text("增加")
                    .Bind(Button.CommandProperty, nameof(CounterViewModel.IncrementCommand))
            }
        };
    }
}

注意Bind()方法第一个参数指定目标依赖属性,第二个参数是绑定路径,convert参数支持内联的值转换,这比XAML中单独定义转换器类的做法灵活不少。命令绑定也通过一行Bind调用完成,整体代码保持了声明式的风格。

五、C# Markup与XAML的对比与选型建议

两种方案各有侧重,可以参考下表来权衡:

对比维度C# MarkupXAML
编译期检查完整,属性错误直接报错属性名部分检查,绑定路径运行时才验证
热重载支持XAML热重载不可用,需依赖C#热重载XAML热重载成熟稳定
代码复用可用方法、循环动态生成控件需要模板、样式等间接手段
设计师协作难以让设计师直接编辑工具链支持较好
重构友好度重命名自动同步字符串绑定路径需手动修改

如果你的团队以C#开发者为主,界面复杂度高且包含大量动态生成逻辑,C# Markup是更合适的选择;如果团队有专门的设计或前端人员参与界面调整,或者非常依赖XAML热重载的即时预览体验,那么保留XAML也完全合理。

实际上两种方式可以在同一个项目中混用,简单的工具页面用C# Markup快速实现,主界面继续用XAML维护,渐进式地评估哪种方式更适合项目,是比较稳妥的落地策略。

MAUIC# MarkupUI编写修改时间:2026-09-06 00:50:45

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260906/51254.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。