You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在.NET MAUI中为自定义ContentView组件正确传递内容?

在.NET MAUI中实现自定义折叠组件的规范内容传递

问题根源

你之前使用TemplateBinding失效,是因为TemplateBinding仅适配ControlTemplate场景,而自定义组件直接继承ContentView时,内部布局属于组件固定内容而非模板,需改用RelativeSource绑定组件自身的可绑定属性。

规范实现方案

1. C# 可绑定属性定义

保留ContentProperty特性,确保组件默认子内容自动映射到CollapseContent,同时正确声明可绑定属性:

[ContentProperty(nameof(CollapseContent))]
public partial class Collapse : ContentView
{
    public static readonly BindableProperty HeaderProperty =
        BindableProperty.Create(nameof(Header), typeof(IView), typeof(Collapse));

    public IView Header
    {
        get => (IView)GetValue(HeaderProperty);
        set => SetValue(HeaderProperty, value);
    }

    public static readonly BindableProperty CollapseContentProperty =
        BindableProperty.Create(nameof(CollapseContent), typeof(IView), typeof(Collapse));

    public IView CollapseContent
    {
        get => (IView)GetValue(CollapseContentProperty);
        set => SetValue(CollapseContentProperty, value);
    }

    public Collapse()
    {
        InitializeComponent();
    }

    private void Expand_Clicked(object sender, EventArgs e)
    {
        ContenuContaineur.IsVisible = !ContenuContaineur.IsVisible;
        Btn_Toggle.Text = ContenuContaineur.IsVisible ? "折叠" : "展开";
    }
}

2. XAML 布局调整

将TemplateBinding替换为RelativeSource绑定,确保可绑定属性与ContentPresenter正确关联:

<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:Cubetrail.Maui.Shared"
             x:Class="Cubetrail.Maui.Shared.Collapse">
    <ContentView.Content>
        <Grid ColumnDefinitions="*,100" RowDefinitions="40,auto">
            <!-- 绑定Header属性 -->
            <ContentPresenter Content="{Binding Header, RelativeSource={RelativeSource AncestorType={x:Type local:Collapse}}}" />
            
            <Button x:Name="Btn_Toggle"
                    Grid.Column="1" 
                    Text="展开"
                    Clicked="Expand_Clicked" />

            <!-- 绑定CollapseContent属性,默认隐藏 -->
            <ContentPresenter x:Name="ContenuContaineur"
                              Content="{Binding CollapseContent, RelativeSource={RelativeSource AncestorType={x:Type local:Collapse}}}"
                              Grid.Row="1" Grid.ColumnSpan="2"
                              IsVisible="False" />
        </Grid>
    </ContentView.Content>
</ContentView>

3. 组件使用方式(与Expander完全一致)

<composants:Collapse>
    <composants:Collapse.Header>
        <Label Text="Header" FontAttributes="Bold" FontSize="Medium" />
    </composants:Collapse.Header>
    <HorizontalStackLayout Padding="10">
        <Label Text="Body Content" />
        <!-- 自定义内容 -->
    </HorizontalStackLayout>
</composants:Collapse>

关于之前"取巧"方法的说明

通过propertyChanged事件手动赋值ContentView.Content的方式虽能运行,但存在明显缺陷:

  • 违背声明式XAML设计理念,将布局逻辑混入C#代码
  • 无法自动支持绑定更新、属性变更通知的完整生命周期
  • 代码冗余,后期维护成本更高

核心结论

在.NET MAUI中,对应Blazor RenderFragment的内容传递机制,就是可绑定属性(BindableProperty)+ ContentPresenter + RelativeSource绑定,这是官方推荐的规范实现方式,能完美复刻MAUI Community Toolkit Expander的使用体验。

内容的提问来源于stack exchange,提问作者Poulpynator

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 22:11:04