如何override/modify Frame 的Content 属性 接受Xamarin.Forms 中的多个View?
How to override/modify the Content property of Frame to accept multiple Views in 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;
}
}
我是这样使用的:
<t:PopupFrame>
<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<t:PopupHeader Text="Copy Deck" />
<t:PopupEntryHeader Text="New Deck Name" />
More XAML here
</StackLayout>
</t:PopupFrame>
有没有什么方法可以让我编写 PopupFrame
代码,使 StackLayout
成为其中的一部分并获取内容。
这是我想要编码的内容:
<t:PopupFrame>
<t:PopupHeader Text="Copy Deck" />
<t:PopupEntryHeader Text="New Deck Name" />
More XAML here
</t:PopupFrame>
如果我是对的,您可以通过将 PopupFrame
class 的 ContentProperty
属性设置为本身就是一个集合的 属性 来实现此目的。这将覆盖 Frame
的 ContentProperty
,即 Content
以允许您将多个视图设置为内容,而不是只有一个,这是 Frame 的默认值...
所以,如果您觉得这一切都不错,请继续阅读。
方法
您可以为 PopupFrame
class 定义一个 ContentProperty
,像这样:
[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;
}
}
然后你就可以做你想做的事情了:
<?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>
我这边同时显示 PopupHeader
和 Label
:
最后是关于 ContentProperty 的一些理论
以下内容直接摘自book of Ch. Petzold on Xamarin.Forms。
在XAML中使用的每个class允许定义一个属性作为内容属性(有时也称为class 的默认值 属性)。对于此内容 属性,不需要 属性 元素标签,并且开始和结束标签内的任何 XML 内容都会自动分配给此 属性。很方便,ContentPage
的内容属性是Content
,StackLayout
的内容属性是Children
,[=88=的内容Frame
的 ] 是 Content
。
这些内容属性已记录在案,但您需要知道在哪里查看。 class 通过使用 ContentPropertyAttribute 指定其内容 属性。如果此属性附加到 class,它会与 class 声明一起出现在在线 Xamarin.Forms API 文档中。这是它在 ContentPage
的文档中的显示方式:
[Xamarin.Forms.ContentProperty("Content")]
public class ContentPage : TemplatedPage
如果大声说出来,听起来有点多余:“Content属性就是ContentPage的内容属性。”
Frame
class 的声明类似:
[Xamarin.Forms.ContentProperty("Content")]
public class Frame : ContentView
StackLayout
没有应用 ContentProperty
属性,但 StackLayout
派生自 Layout<View>
,并且 Layout<T>
具有 ContentProperty
属性:
[Xamarin.Forms.ContentProperty("Children")]
public abstract class Layout<T> : Layout, IViewContainer<T>
where T : View
ContentProperty
属性被继承自Layout<T>
的class属性,所以Children
是[=26=的内容属性 ].
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;
}
现在您可以使用
<?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>
这是我的 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;
}
}
我是这样使用的:
<t:PopupFrame>
<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<t:PopupHeader Text="Copy Deck" />
<t:PopupEntryHeader Text="New Deck Name" />
More XAML here
</StackLayout>
</t:PopupFrame>
有没有什么方法可以让我编写 PopupFrame
代码,使 StackLayout
成为其中的一部分并获取内容。
这是我想要编码的内容:
<t:PopupFrame>
<t:PopupHeader Text="Copy Deck" />
<t:PopupEntryHeader Text="New Deck Name" />
More XAML here
</t:PopupFrame>
如果我是对的,您可以通过将 PopupFrame
class 的 ContentProperty
属性设置为本身就是一个集合的 属性 来实现此目的。这将覆盖 Frame
的 ContentProperty
,即 Content
以允许您将多个视图设置为内容,而不是只有一个,这是 Frame 的默认值...
所以,如果您觉得这一切都不错,请继续阅读。
方法
您可以为 PopupFrame
class 定义一个 ContentProperty
,像这样:
[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;
}
}
然后你就可以做你想做的事情了:
<?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>
我这边同时显示 PopupHeader
和 Label
:
最后是关于 ContentProperty 的一些理论
以下内容直接摘自book of Ch. Petzold on Xamarin.Forms。
在XAML中使用的每个class允许定义一个属性作为内容属性(有时也称为class 的默认值 属性)。对于此内容 属性,不需要 属性 元素标签,并且开始和结束标签内的任何 XML 内容都会自动分配给此 属性。很方便,ContentPage
的内容属性是Content
,StackLayout
的内容属性是Children
,[=88=的内容Frame
的 ] 是 Content
。
这些内容属性已记录在案,但您需要知道在哪里查看。 class 通过使用 ContentPropertyAttribute 指定其内容 属性。如果此属性附加到 class,它会与 class 声明一起出现在在线 Xamarin.Forms API 文档中。这是它在 ContentPage
的文档中的显示方式:
[Xamarin.Forms.ContentProperty("Content")]
public class ContentPage : TemplatedPage
如果大声说出来,听起来有点多余:“Content属性就是ContentPage的内容属性。”
Frame
class 的声明类似:
[Xamarin.Forms.ContentProperty("Content")]
public class Frame : ContentView
StackLayout
没有应用 ContentProperty
属性,但 StackLayout
派生自 Layout<View>
,并且 Layout<T>
具有 ContentProperty
属性:
[Xamarin.Forms.ContentProperty("Children")]
public abstract class Layout<T> : Layout, IViewContainer<T>
where T : View
ContentProperty
属性被继承自Layout<T>
的class属性,所以Children
是[=26=的内容属性 ].
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;
}
现在您可以使用
<?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>