如何覆盖/修改 Frame 的 Content 属性以接受 Xamarin.Forms 中的多个视图?

Ala*_*an2 11 c# xaml contentproperty xamarin xamarin.forms

这是我拥有的C#模板代码:

public class PopupFrame : Frame
{
    public PopupFrame()
    {
        this.SetDynamicResource(BackgroundColorProperty, "PopUpBackgroundColor");
        this.SetDynamicResource(CornerRadiusProperty, "PopupCornerRadius");
        HasShadow = true;
        HorizontalOptions = LayoutOptions.FillAndExpand;
        Padding = 0;
        VerticalOptions = LayoutOptions.Center;
    }
}
Run Code Online (Sandbox Code Playgroud)

我是这样使用它的:

<t:PopupFrame>
   <StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
         <t:PopupHeader Text="Copy Deck" />
         <t:PopupEntryHeader Text="New Deck Name" />
                
                More XAML here
   </StackLayout>
</t:PopupFrame>
Run Code Online (Sandbox Code Playgroud)

有什么方法可以编码,PopupFrame以便它StackLayout是它的一部分并且它需要内容。

这是我想编码的内容:

<t:PopupFrame>
   <t:PopupHeader Text="Copy Deck" />
   <t:PopupEntryHeader Text="New Deck Name" />
                
       More XAML here

</t:PopupFrame>
Run Code Online (Sandbox Code Playgroud)

Dec*_*oth 10

如果我是对的,您可以通过将类的ContentProperty属性设置PopupFrame为本身就是集合的属性来实现这一点。这将覆盖ContentPropertyFrameContent允许您设置多个视图的内容,而不只是一个它是框架默认...

所以,如果这一切听起来不错,请继续阅读。

操作方法

您可以ContentProperty为您的PopupFrame班级定义一个,如下所示:

[Xamarin.Forms.ContentProperty("Contents")]
class PopupFrame : Frame
{
    StackLayout contentStack { get; } = new StackLayout();

    public IList<View> Contents { get => contentStack.Children; }


    public PopupFrame()
    {
        Content = contentStack;

        HasShadow = true;
        HorizontalOptions = LayoutOptions.FillAndExpand;
        Padding = 0;
        VerticalOptions = LayoutOptions.Center;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你就可以做你想做的事情:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:t="clr-namespace:popupframe"
             x:Class="popupframe.MainPage">

    <StackLayout>
        <t:PopupFrame>
            <t:PopupHeader Text="Test header"/>
            <Label Text="Test content"/>
        </t:PopupFrame>
    </StackLayout>

</ContentPage>
Run Code Online (Sandbox Code Playgroud)

我这边的作品同时显示了PopupHeaderLabel

在此处输入图片说明

最后是关于 ContentProperty 的一些理论

以下内容是从Ch书上逐字取来的Xamarin.Forms 上的 Petzold

XAML 中使用的每个类都允许将一个属性定义为内容属性(有时也称为类的默认属性)。对于此内容属性,不需要属性元素标记,并且开始和结束标记中的任何 XML 内容都会自动分配给此属性。很方便,内容特性ContentPageContent,内容特性StackLayoutChildren,与内容属性FrameContent

这些内容属性已记录在案,但您需要知道在哪里查看。类使用 ContentPropertyAttribute 指定其内容属性。如果此属性附加到类,则它会与类声明一起出现在在线 Xamarin.Forms API 文档中。以下是它在文档中的显示方式ContentPage

[Xamarin.Forms.ContentProperty("Content")]
public class ContentPage : TemplatedPage
Run Code Online (Sandbox Code Playgroud)

如果你大声说出来,听起来有点多余:“Content 属性是 ContentPage 的内容属性。”

Frame类的声明类似:

[Xamarin.Forms.ContentProperty("Content")]
public class Frame : ContentView
Run Code Online (Sandbox Code Playgroud)

StackLayout没有ContentProperty应用属性,但StackLayout派生自Layout<View>,并且Layout<T>有一个ContentProperty属性:

[Xamarin.Forms.ContentProperty("Children")]
public abstract class Layout<T> : Layout, IViewContainer<T>
where T : View
Run Code Online (Sandbox Code Playgroud)

ContentProperty属性是由从导出类继承Layout<T>,所以Children是的内容属性StackLayout


Jai*_*pta 5

PopupFrame.cs

public class PopupFrame : Frame
{
    StackLayout PopupContent;
    public IList<View> Body
    {
        get => PopupContent.Children;
    }
    public PopupFrame()
    {

        PopupContent = new StackLayout();

        SetDynamicResource(Frame.BackgroundColorProperty, "PopUpBackgroundColor");
        SetDynamicResource(Frame.CornerRadiusProperty, "PopupCornerRadius");
        HasShadow = true;
        HorizontalOptions = LayoutOptions.FillAndExpand;
        Padding = 0;
        VerticalOptions = LayoutOptions.Center;

        Content = PopupContent;
    }
Run Code Online (Sandbox Code Playgroud)

现在你可以使用

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:t="clr-namespace:popupframe"
             x:Class="popupframe.MainPage">

    <StackLayout>
       <t:PopupFrame>
         <t:PopupFrame.Body>
             <t:PopupHeader Text="Test header"/>
             <Label Text="Test content"/>
           </t:PopupFrame.Body>
        </t:PopupFrame>
    </StackLayout>

</ContentPage>
Run Code Online (Sandbox Code Playgroud)