https://www.cnblogs.com/functionMC/p/17001254.html
FlexLayout、BindableLayout、StateContainer
一、FlexLayout弹性布局
1、FlexLayout弹性布局,和前端的Flex弹性布局,几乎一样。FlexLayout是容器,可以定义Direction/主轴方向、Wrap/子元素在主轴方向上是否换行/列、JustityContent/AlignItems/AlignContent子元素整体对齐方式。同时,在子元素上可以通过附加属性,定义子元素的个体行为,如Order,定义子元素排列顺序;Basis/Grow/Shrink,定义子元素主轴方向的尺寸形为;AlighSeft,定义子元素在交叉轴方向的对齐行为。
2、使用FlexLayout布局时的经验
确定子元素排列的主轴方向Direction,Row-由左至右水平排列(默认值),Column-由上至下垂直排列,或者RowReverse-由右至左水平排列、ColumnReverse-由下至上垂直排列
确定子元素在主轴方向上是否换行Wrap,NoWrap-不换行(默认值)、Wrap-换行、Reverse-反方向换行
确定子元素整体在主轴和交叉轴上的对齐方式,JustifyContent-主轴方向上的对齐方式、AlignItems-NoWap时交叉轴方向上的对齐方式、AlignContent-Wap时交叉轴方向上的对齐方式
确定子元素个体在主轴和交叉轴上的排列顺序、缩放和对齐行为,Order-排列顺序、Basis/Grow/Shrink-NoWap时主轴方向上的尺寸和缩放、AlignSeft-NoWap时交叉轴方向上的对齐
如下图所示:
3、使用FlexLayout完成圣杯布局
<ContentPage
x:Class="MauiApp12.MainPage"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
BackgroundColor="{DynamicResource PageBackgroundColor}">
<!-- 外层FlexLayout,主轴为Column,自上而下垂直排列,分为三行,不换行 -->
<!-- JustifyContent主轴-垂直方向的对齐方式为Start,AlignItems交叉轴-水平方向对齐方式为Stretch/自动扩展 -->
<FlexLayout
AlignItems="Stretch"
Direction="Column"
JustifyContent="Start"
Wrap="NoWrap">
<Label
BackgroundColor="Red"
HorizontalTextAlignment="Center"
Text="Header" />
<!--内层FlexLayout,作为外层FlexLayout的子元素,附加属性FlexLayout.Grow为1,在交叉轴-水平方向上填满剩余空间-->
<!--内层FlexLayout,主轴方向为Row,自左向右水平排列,不换行-->
<FlexLayout
Direction="Row"
FlexLayout.Grow="1"
Wrap="NoWrap">
<!--内层FlexLayout的子元素,BoxView设置附加属性FlexLayout.Basis,主轴方向的基础尺寸为50-->
<BoxView FlexLayout.Basis="50" Color="Yellow" />
<!--内层FlexLayout的子元素,Lable设置附加属性FlexLayout.Grow,主轴方向上扩展填满剩余空间-->
<Label
BackgroundColor="Green"
FlexLayout.Grow="1"
Text="Content" />
<BoxView FlexLayout.Basis="50" Color="Yellow" />
</FlexLayout>
<Label
BackgroundColor="Gray"
HorizontalTextAlignment="Center"
Text="Footer" />
</FlexLayout>
</ContentPage>
二、绑定布局BindableLayout,以附加属性的形式,在宿主布局容器内,实现一个集合展示。实现的功能,与ListView或CollectionView类似,在条目数较少、无滚动、无选择按钮情况时,可以使用BindableLayout。
1、定义一个ViewModel,作为数据源
//直接New一个Employee集合
//ImageSource为Resources/Images目录下的图像
public partial class MainPageViewModel: ObservableObject
{
[ObservableProperty]
private List<Employee> employees = new List<Employee>
{
new Employee{Name = "HeLiu",ImageSource="he_liu.png"},
new Employee{Name = "HaiShang",ImageSource="hai_shang.png"},
new Employee{Name = "LuoRi",ImageSource="luo_ri.png"},
new Employee{Name = "GongYuan",ImageSource="gong_yuan.png"},
};
}
2、使用BindableLayout
<ContentPage
x:Class="MauiApp12.MainPage"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:vm="clr-namespace:MauiApp12.ViewModels">
<!--直接创建ViewModel对象,并设置为页面的BindingContext-->
<ContentPage.BindingContext>
<vm:MainPageViewModel />
</ContentPage.BindingContext>
<!--BindableLayout.ItemsSource,数据源-->
<!--BindableLayout.ItemTemplate,数据模板-->
<!--BindableLayout.EmptyView,无数据时显示的文字提示-->
<!--BindableLayout.EmptyView,还支持定义复杂的外观-->
<!--BindableLayout.ItemTemplateSelector,相当于迭代中的if,详见数据模板的DataTemplateSelector-->
<StackLayout
BindableLayout.EmptyView="无数据"
BindableLayout.ItemsSource="{Binding Employees}"
Orientation="Horizontal">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Image
Aspect="AspectFill"
HeightRequest="44"
Source="{Binding ImageSource}"
WidthRequest="44" />
</DataTemplate>
</BindableLayout.ItemTemplate>
<!--<BindableLayout.EmptyView>
<Label Text="数据为空时显示的外观"/>
</BindableLayout.EmptyView>-->
</StackLayout>
</ContentPage>
三、状态容器StateContainer,以附加属性的形式,在宿主布局容器内,根据不同的状态条件,显示不同的外观。
1、安装Nuget包,Community.Toolkit.Maui,并在入口文件MauiProgram.cs文件中设置【builder.UseMauiApp
2、定义一个ViewModel,作为数据源
public partial class MainPageViewModel: ObservableObject
{
[ObservableProperty]
private string myCurrentState;
[RelayCommand]
private void ChangeMyCurrentStateLoading()
{
MyCurrentState = "Loading";
}
[RelayCommand]
private void ChangeMyCurrentStateSuccess()
{
MyCurrentState = "Success";
}
[RelayCommand]
private void ChangeMyCurrentStateEmpty()
{
MyCurrentState = "";
}
}
3、使用StateContainer
<ContentPage
......
xmlns:tk="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
xmlns:vm="clr-namespace:MauiApp12.ViewModels">
<!-- 直接创建ViewModel对象,并设置为页面的BindingContext -->
<ContentPage.BindingContext>
<vm:MainPageViewModel />
</ContentPage.BindingContext>
<VerticalStackLayout>
<!--tk:StateContainer.CurrentState的值和tk:StateView.StateKey匹配-->
<VerticalStackLayout tk:StateContainer.CurrentState="{Binding MyCurrentState}">
<tk:StateContainer.StateViews>
<!--tk:StateContainer.CurrentState的值为Loading时,显示如下内容-->
<VerticalStackLayout tk:StateView.StateKey="Loading">
<ActivityIndicator IsRunning="True" />
<Label Text="加载中..." />
</VerticalStackLayout>
<!--tk:StateContainer.CurrentState的值为Success时,显示如下内容-->
<Label tk:StateView.StateKey="Success" Text="Success!" />
</tk:StateContainer.StateViews>
<!--tk:StateContainer.CurrentState的值为Null或空字符串时默认显示的内容-->
<Label Text="默认内容" />
</VerticalStackLayout>
<!--按钮更改MyCurrentState值-->
<Button Command="{Binding ChangeMyCurrentStateLoadingCommand}" Text="Loading" />
<Button Command="{Binding ChangeMyCurrentStateSuccessCommand}" Text="Success" />
<Button Command="{Binding ChangeMyCurrentStateEmptyCommand}" Text="Empty" />
</VerticalStackLayout>
</ContentPage>