在UI设计中,页面结构非常紧张,良好的结构不仅可以有效的使用空间,还能提升交互体验,以达到事半功倍的效果。所以对于Avalonia UI初学者来说,结构控件的了解与学习也非常的紧张,本日以一些小例子,简述Avalonia UI框架中结构控件的使用,仅供学习分享使用,如有不敷之处,还请指正。
结构体系
结构体系描述了容器对元素集合的成员进行测量和排列的过程。结构是一个麋集的过程,Children集合越大,进行的计算越多。每次对子控件更改位置,都可能触发结构体系的新计算,所以不必要的调用可能会导致应用步伐的性能降落。结构体系对子元素集合的每个成员完成两个传递:测量传递和排列传递。每个Panel提供本身的MeasureOverride和ArrangeOverride方法,以实现其特定的结构举动。常用的结构面板有以下几种:
- Panel 将所有子元素结构以填充 Panel 的边界
- Canvas 界说一个区域,您可以在此中使用相对于 Canvas 区域的坐标明确定位子元素
- DockPanel 界说一个区域,此中您可以相对于彼此将子元素水平或垂直地排列
- Grid 界说由列和行组成的机动网格区域
- RelativePanel 将子元素相对于其他元素或面板本身排列
- StackPanel 将子元素排列成一行,可以是水平或垂直方向
- WrapPanel 将子元素按从左到右的次序放置,当内容到达容器框的边缘时,将在下一行中断。后续排序次序是次序从上到下或从右到左,这取决于 Orientation 属性的值。
注意:在 WPF 中,Panel 是一个抽象类,通常使用没有行/列的 Grid 来结构多个控件以填充可用空间。在 Avalonia 中,Panel 是一个可用的控件,其结构举动与没有行/列的 Grid 相同,但运行时占用更少的资源。
对齐与边距
在Avalonia UI中,提供了四个常用属性(HorizontalAlignment、Margin、Padding和VerticalAlignment),用于精确定位子元素。它们是控制元素在应用步伐中位置的底子。主要如下:
- HorizontalAlignment属性声明了要应用于子元素的水平对齐特性,常用的属性值有四个:
- Left 子元素与父元素分配的结构空间的左侧对齐。
- Center 子元素与父元素分配的结构空间的中心对齐。
- Right 子元素与父元素分配的结构空间的右侧对齐。
- Stretch (默认) 子元素被拉伸以填充父元素分配的结构空间。明确的Width和Height值优先级更高。
- VerticalAlignment属性声明了要应用于子元素的垂直对齐特性,常用的属性值有四个:
- Top 子元素与父元素分配的结构空间的顶部对齐。
- Center 子元素与父元素分配的结构空间的中心对齐。
- Bottom 子元素与父元素分配的结构空间的底部对齐。
- Stretch(默认) 子元素被拉伸以填充父元素分配的结构空间。明确的Width和Height值优先级更高。
- Margin属性描述了元素与其子元素或同级元素之间的距离。Margin值可以是相同的,通过使用像Margin="20"的语法,元素将使用相同的20个设备独立像素的Margin。Margin值也可以是四个不同的值,每个值描述了应用于左、上、右和下的不同边距(按次序),如Margin="0,10,5,25"。在很多情况下,统一的边距是不合适的。在这些情况下,可以应用非统一间距。精确使用Margin属性可以非常精确地控制元素的渲染位置及其相邻元素和子元素的渲染位置。
- Padding属性描述了元素与其内容之间的距离,在大多数方面与Margin相似。Padding属性仅暴露在少数类上,主要是为了方便。Border、TemplatedControl、和TextBlock是暴露了Padding属性的类的范例。Padding属性通过指定的Thickness值扩大了子元素的有效尺寸。
注意:HorizontalAlignment和VerticalAlignment属性描述了一个子元素应该如安在父元素分配的结构空间内定位。元素上明确设置的Height和Width属性的优先级高于Stretch属性。如果明确设置了Height和Width,再将HorizontalAlignment设置为Stretch,这样会忽略Stretch属性。
对齐与边距应用示例如下所示:- <Window xmlns="https://github.com/avaloniaui"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- x:
- Title="AvaloniaApplication2">
- <Border Background="LightBlue"
- BorderBrush="Black"
- BorderThickness="2"
- Padding="15">
- <StackPanel Background="White"
- <Panel>
- <TextBlock Background="LightGray" Text="Left" Width="100" Height="20" HorizontalAlignment="Left" />
- <TextBlock Background="LightGray" Text="Right" Width="100" Height="20" HorizontalAlignment="Right"/>
- <TextBlock Background="LightGray" Text="Top" Width="100" Height="20" VerticalAlignment="Top" />
- <TextBlock Background="LightGray" Text="Bottom" Width="100" Height="20" VerticalAlignment="Bottom"/>
- </Panel>HorizontalAlignment="Center"
- <Panel>
- <TextBlock Background="LightGray" Text="Left" Width="100" Height="20" HorizontalAlignment="Left" />
- <TextBlock Background="LightGray" Text="Right" Width="100" Height="20" HorizontalAlignment="Right"/>
- <TextBlock Background="LightGray" Text="Top" Width="100" Height="20" VerticalAlignment="Top" />
- <TextBlock Background="LightGray" Text="Bottom" Width="100" Height="20" VerticalAlignment="Bottom"/>
- </Panel>VerticalAlignment="Top">
- <TextBlock Margin="5,0"
- <Panel>
- <TextBlock Background="LightGray" Text="Left" Width="100" Height="20" HorizontalAlignment="Left" />
- <TextBlock Background="LightGray" Text="Right" Width="100" Height="20" HorizontalAlignment="Right"/>
- <TextBlock Background="LightGray" Text="Top" Width="100" Height="20" VerticalAlignment="Top" />
- <TextBlock Background="LightGray" Text="Bottom" Width="100" Height="20" VerticalAlignment="Bottom"/>
- </Panel> FontSize="18"
- <Panel>
- <TextBlock Background="LightGray" Text="Left" Width="100" Height="20" HorizontalAlignment="Left" />
- <TextBlock Background="LightGray" Text="Right" Width="100" Height="20" HorizontalAlignment="Right"/>
- <TextBlock Background="LightGray" Text="Top" Width="100" Height="20" VerticalAlignment="Top" />
- <TextBlock Background="LightGray" Text="Bottom" Width="100" Height="20" VerticalAlignment="Bottom"/>
- </Panel> HorizontalAlignment="Center">
- Alignment, Margin and Padding Sample
- </TextBlock>
- <Button HorizontalAlignment="Left" Margin="20">Button 1</Button>
- <Button HorizontalAlignment="Right" Margin="10">Button 2</Button>
- <Button HorizontalAlignment="Stretch">Button 3</Button>
- </StackPanel>
- </Border>
- </Window>
复制代码 示例效果如下图所示:

Panel控件
Panel是Avalonia提供的结构支持的元素的基类,默认情况下,Panel和没有行列个Grid相同,可以采用对齐或边距(HorizontalAlignment、Margin、Padding和VerticalAlignment)进行定位,但相对于Grid等复杂结构容器,Panel运行时占用的资源较少。示例如下所示:- <Panel>
- <TextBlock Background="LightGray" Text="Left" Width="100" Height="20" HorizontalAlignment="Left" />
- <TextBlock Background="LightGray" Text="Right" Width="100" Height="20" HorizontalAlignment="Right"/>
- <TextBlock Background="LightGray" Text="Top" Width="100" Height="20" VerticalAlignment="Top" />
- <TextBlock Background="LightGray" Text="Bottom" Width="100" Height="20" VerticalAlignment="Bottom"/>
- </Panel>
复制代码 示例效果如下所示:
如果将Panel中的元素换成Button,将会有不同的效果,示例代码如下:- <Panel>
- <TextBlock Background="LightGray" Text="Left" Width="100" Height="20" HorizontalAlignment="Left" />
- <TextBlock Background="LightGray" Text="Right" Width="100" Height="20" HorizontalAlignment="Right"/>
- <TextBlock Background="LightGray" Text="Top" Width="100" Height="20" VerticalAlignment="Top" />
- <TextBlock Background="LightGray" Text="Bottom" Width="100" Height="20" VerticalAlignment="Bottom"/>
- </Panel>
复制代码 示例效果如下所示:
思考一下:都是Panel结构,将TextBlock换成Button,为什么效果会不同呢?
Canvas
Canvas(画布容器)允许按绝对坐标(x,y)定位子元素。子元素可以绘制在不同的位置,也可以绘制在同一个位置,如果两个控件在Canvas容器中的位置相同,则依据出现的次序进行表现。Canvas提供了最机动的结构支持,Height和Width属性界说画布的大小,此中的元素被赋予相对于Canvas区域的绝对坐标。通过四个附加属性 (Canvas.Left、Canvas.Top、Canvas.Right 和 Canvas.Bottom )来精确地控制对象在 Canvas 内的位置,从而使开发人员可以精确定位和排列元素在屏幕上的位置。
Canvas结构示例代码,如下所示:- <Panel>
- <TextBlock Background="LightGray" Text="Left" Width="100" Height="20" HorizontalAlignment="Left" />
- <TextBlock Background="LightGray" Text="Right" Width="100" Height="20" HorizontalAlignment="Right"/>
- <TextBlock Background="LightGray" Text="Top" Width="100" Height="20" VerticalAlignment="Top" />
- <TextBlock Background="LightGray" Text="Bottom" Width="100" Height="20" VerticalAlignment="Bottom"/>
- </Panel>
复制代码 示例效果如下所示:
在Canvas中,如果没有明确设置子元素在容器中的位置,则默认位于左上角,即Left,Top为0。另外,Canvas的默认举动是允许子元素绘制在父Canvas边界之外,如果不希望出现这种情况,可以设置ClipToBounds属性为True,会自动裁剪边界之外的内容。
在上述示例中,Canvas.Left,Canvas.Top,Canvas.Bottom,Canvas.Right,作为Canvas的附加属性,应用在Canvas容器中的子元素上,则前缀“Canvas.”不可以省略。如果省略,且子元素本身也有Left,Top等属性,则会造成编译器无法准确识别。
DockPanel
DockPanel(停靠面板)使用附加属性DockPanel.Dock来设置子内容元素在容器边缘的位置。当 DockPanel.Dock 设置为 Top 或 Bottom 时,它会将子元素放置在彼此的上方或下方。当 DockPanel.Dock 设置为 Left 或 Right 时,它会将子元素放置在彼此的左侧或右侧。LastChildFill 属性决定了末了一个作为 DockPanel 子元素添加的元素的位置。
如果没有指定DockPanel的Width和Height属性,它的大小根据内容来确定。大小可以根据其子元素的大小进行增长或减小。然而,当指定了这些属性并且没有足够的空间来容纳下一个指定的子元素时,DockPanel 不会表现该子元素或随后的子元素,并且不会对随后的子元素进行测量。
DockPanel示例源码,如下所示:- <DockPanel LastChildFill="True">
- <Border Height="25" Background="SkyBlue" BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Top">
- <TextBlock Foreground="Black">Dock = "Top"</TextBlock>
- </Border>
- <Border Height="25" Background="SkyBlue" BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Top">
- <TextBlock Foreground="Black">Dock = "Top"</TextBlock>
- </Border>
- <Border Height="25" Background="LemonChiffon" BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Bottom">
- <TextBlock Foreground="Black">Dock = "Bottom"</TextBlock>
- </Border>
- <Border Width="200" Background="PaleGreen" BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Left">
- <TextBlock Foreground="Black">Dock = "Left"</TextBlock>
- </Border>
- <Border Background="White" BorderBrush="Black" BorderThickness="1">
- <TextBlock Foreground="Black">This content will "Fill" the remaining space</TextBlock>
- </Border>
- </DockPanel>
复制代码 示例效果如下所示:
注意,默认情况下,DockPanel 元素的末了一个子元素将“填充”剩余的未分配空间。如果不希望出现这种情况,可以将 LastChildFill 属性设置为 false。
Grid
Grid容器结合了绝对定位和表格数据控件的功能。Grid允许界说机动的行和列分组,并且可以在多个Grid之间共享大小信息。在Grid控件中,通过ColumnDefinitions="Auto,*,*,*,*" RowDefinitions="Auto,Auto,*,Auto"实现界说行列,多行多列用逗号隔开,子元素通过Grid.Row,Grid.Column附加属性进行定位。在XAML中,行列的大小可以通过几种方式进行设置:
- 通过Star(*)进行设置,如Width="*"或Width="2*",则该行列会按比例得到剩余可用空间。
- 通过Auto进行设置,如Width="Auto",则行或列会根据内容的大小进行分配空间。
- 绝对大小,默认单位为像素值,如Width="100",表现宽度为100px。
如下Grid代码界说了4行5列,具体如下所示:- <Panel>
- <TextBlock Background="LightGray" Text="Left" Width="100" Height="20" HorizontalAlignment="Left" />
- <TextBlock Background="LightGray" Text="Right" Width="100" Height="20" HorizontalAlignment="Right"/>
- <TextBlock Background="LightGray" Text="Top" Width="100" Height="20" VerticalAlignment="Top" />
- <TextBlock Background="LightGray" Text="Bottom" Width="100" Height="20" VerticalAlignment="Bottom"/>
- </Panel>
复制代码 示例效果如下所示:
StackPanel
StackPanel(栈面板)允许在指定的方向上堆叠元素,默认的堆叠方法是垂直的,如果想要水平方向排列,可以通过Orientation属性进行设置,来控制子元素内容的排列方向。
StackPanel示例代码如下所示:- <StackPanel HorizontalAlignment="Center" VerticalAlignment="Top" Spacing="25">
- <Button Content="Button 1" />
- <Button Content="Button 2" />
- <Button Content="Button 3" />
- </StackPanel>
复制代码 示例效果如下所示:
WrapPanel
WrapPanel用于按照从指定的次序定位子元素,并在其父容器的边缘到达时将内容换行。WrapPanel和StackPanel一样,可以通过Orientation属性指定子元素排列的方向,默认为水平排列。
WrapPanel示例代码如下所示:- <StackPanel HorizontalAlignment="Center" VerticalAlignment="Top" Spacing="25">
- <Button Content="Button 1" />
- <Button Content="Button 2" />
- <Button Content="Button 3" />
- </StackPanel>Button 1 Button 2 Button 3 Button 4
复制代码 示例效果如下所示:
UniformGrid
UniformGrid提供统一的网格结构面板,此网格结构面板中的所有单位格大小相同,与Grid不同,此网格结构面板不支持表现设置行,和列,也没有Grid.Row,Grid.Column等附加属性,它主要用于表现大小相同的子元素控件。UniformGrid常用属性如下:
- 行和列:UniformGrid 使用 Rows 和 Columns 属性来确定其子元素的结构。如果只设置此中一个属性,UniformGrid 将自动计算另一个属性,以创建适合子元素总数的网格。如果两个属性都不设置,UniformGrid 默认为 1 行 1 列的网格。
- FirstColumn:FirstColumn 属性允许您在网格的第一行中留下肯定数量的空单位格。
UniformGrid示例如下所示:- <Panel>
- <TextBlock Background="LightGray" Text="Left" Width="100" Height="20" HorizontalAlignment="Left" />
- <TextBlock Background="LightGray" Text="Right" Width="100" Height="20" HorizontalAlignment="Right"/>
- <TextBlock Background="LightGray" Text="Top" Width="100" Height="20" VerticalAlignment="Top" />
- <TextBlock Background="LightGray" Text="Bottom" Width="100" Height="20" VerticalAlignment="Bottom"/>
- </Panel>
复制代码 在上面的示例中,每个 Rectangle 被自动分配到网格中的一个单位格,按照它们被添加的次序进行分配。示例效果如下所示:
结构嵌套
在实际应用中,不同的Panel可以相互嵌套,以创建复杂的结构。固然理论上可以无穷嵌套面板元素,但嵌套越多,性能越低。所以熟练掌握各种结构容器的特点,才能根据业务需求,采用合理的结构面板,这样不仅能提升性能,还会起到事半功倍的效果。
以上就是《Avalonia系列文章之结构简介》的全部内容,希望可以抛砖引玉,一起学习,共同进步。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |