Xamarin.Forms 如何创建自定义控件,用户可以向其中添加任何类型的视图?

How to create a custom control that user can add any kinds of view into it in Xamarin.Forms?

我想创建一个自定义控件,可以让用户将任何视图添加到特定位置,如下所示:

MyCustomControl.xaml

<ContentView ...>

    <!-- My customizations ... -->

    <StackLayout>
    <!-- Everything added by user should goes here -->
    </StackLayout>

    <!-- My other customizations ... -->

</ContentView>

使用时:

<ContentPage>

    <controls:MyCustomControl>
        <Label />
        <Image />
        ...
    <controls:MyCustomControl>

</ContentPage>

我该怎么做?

我将post 这里介绍一种方法,但还有其他方法。从你的问题来看,我假设你想在不同的地方重用一个 ContentView 并允许在你实例化它时更改该内容视图的一部分。我假设您要在 XAML 中指定自定义部分。您可以使用以下模式来实现此目的:

创建您的 ContentView 并为自定义部分添加可绑定的 属性:

ContentViewWithCustomPart.xaml

<ContentView.Content>
    <StackLayout>
        <Label Text="I'm always here!" />
        <StackLayout x:Name="StackToHoldCustomStuff">
            <!-- Stuff goes here injected by bindable property -->
        </StackLayout>
    </StackLayout>
</ContentView.Content>

ContenViewWithCustomPart.xaml.cs

public partial class ContentViewWithCustomPart : ContentView
{
    public static readonly BindableProperty CustomViewProperty = 
            BindableProperty.Create(nameof(CustomView), typeof(View), typeof(ContentViewWithCustomPart), propertyChanged: OnViewChanged);

    static void OnViewChanged(object bindable, object oldValue, object newValue)
    {
        var page = (ContentViewWithCustomPart)bindable;
        page.StackToHoldCustomStuff.Children.Clear();
        if (newValue != null) page.StackToHoldCustomStuff.Children.Add((View)newValue);
    }

    public View CustomView { get => (View)GetValue(CustomViewProperty); set => SetValue(CustomViewProperty, value); }

    public ContentViewWithCustomPart()
    {
       InitializeComponent();
    }
}

演示页面中的用法:

<ContentPage.Content>
    <StackLayout>
        <cv:ContentViewWithCustomPart>             
            <cv:ContentViewWithCustomPart.CustomView>
                <Label Text="I'm a custom bit!" />
            </cv:ContentViewWithCustomPart.CustomView>
        </cv:ContentViewWithCustomPart>
    </StackLayout>
</ContentPage.Content>

结果: