跨平台WPF框架Avalonia教程 十四

DataGrid 数据表格

数据表格以自定义的网格形式展示重复的数据。该控件可以进行样式定制、模板化和绑定。

数据表格需要绑定到一个可观察的集合(Observable Collection),该集合可以在相关的数据上下文中找到。

信息

要了解数据上下文 背后的概念,请查看这里

信息

数据表格位于附加的 Avalonia UI 包中。要在您的项目中使用数据表格,您必须引用Avalonia.Controls.DataGrid NuGet 包,并引用其使用的样式,参见下面。

NuGet包引用

您必须安装数据表格的 NuGet 包,有几种方法可以做到这一点。您可以使用您的IDE的项目菜单中的管理NuGet包

或者,您可以在命令行中运行以下指令:

dotnet add package Avalonia.Controls.DataGrid

或直接在项目(.csproj)文件中添加包引用:

<PackageReference Include="Avalonia.Controls.DataGrid" Version="11.0.0" />

注意

请注意,您必须始终安装与您正在使用的 Avalonia UI 版本匹配的数据表格版本。

引入数据表格样式

您必须引用数据表格的主题,以包含数据表格使用的附加样式。您可以通过向应用程序(App.axaml文件)添加<StyleInclude>元素来实现这一点。

例如:

<Application.Styles>
    <FluentTheme />
    <StyleInclude Source="avares://Avalonia.Controls.DataGrid/Themes/Fluent.xaml"/>
</Application.Styles>

常用属性

您可能经常使用以下属性:

属性 描述
AutoGenerateColumns 是否根据绑定项数据源属性名称自动生成列头。 (默认关闭)
ItemsSource 作为控件数据源的绑定集合。
IsReadOnly 当为true时,将绑定方向设置为单向。默认值为false,网格将接受对绑定数据的更改。
CanUserReorderColumns 用户是否可以通过拖动列头更改列的显示顺序。 (默认关闭)
CanUserResizeColumns 用户是否可以使用指针调整列宽度。 (默认关闭)
CanUserSortColumns 用户是否可以通过单击列头对列进行排序。 (默认关闭)

更多信息

这个示例将生成一个基本的数据表格,列头名称将根据项类自动生成。项目数据源绑定到主窗口的 ViewModel。

<DataGrid Margin="20" ItemsSource="{Binding People}" 
          AutoGenerateColumns="True" IsReadOnly="True" 
          GridLinesVisibility="All"
          BorderThickness="1" BorderBrush="Gray">
</DataGrid>

ViewModel

using AvaloniaControls.Models;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace AvaloniaControls.ViewModels
{
    public class MainWindowViewModel : ViewModelBase
    {
        public ObservableCollection<Person> People { get; }

        public MainWindowViewModel()
        {
            var people = new List<Person> 
            {
                new Person("Neil", "Armstrong"),
                new Person("Buzz", "Lightyear"),
                new Person("James", "Kirk")
            };
            People = new ObservableCollection<Person>(people);
        }
    }
}

数据源 Person 类

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    
    public Person(string firstName , string lastName)
    {
        FirstName = firstName;
        LastName = lastName;
    }
}

信息

这些示例使用了MVVM模式和数据绑定到一个ObservableCollection。要了解更多有关数据绑定背后的概念,请参阅这里

通常来说,从数据源中获取的属性名称通常不会成为合适的列名。下面这个示例为表格添加了自定义的列头名称。它还允许列重新排序和调整大小,并禁用了默认的列排序选项:

<DataGrid Margin="20" ItemsSource="{Binding People}"
          IsReadOnly="True"
          CanUserReorderColumns="True"
          CanUserResizeColumns="True"
          CanUserSortColumns="False"
          GridLinesVisibility="All"
          BorderThickness="1" BorderBrush="Gray">
  <DataGrid.Columns>
     <DataGridTextColumn Header="First Name"  Binding="{Binding FirstName}"/>
     <DataGridTextColumn Header="Last Name" Binding="{Binding LastName}" />
  </DataGrid.Columns>
</DataGrid>

这个示例展示了数据表格如何接受更改并更新底层集合,并使用不同的列类型来编辑数据:

<DataGrid Margin="20" ItemsSource="{Binding People}"        
          GridLinesVisibility="All"
          BorderThickness="1" BorderBrush="Gray">
  <DataGrid.Columns>
     <DataGridTextColumn Header="First Name"  Binding="{Binding FirstName}"/>
     <DataGridTextColumn Header="Last Name" Binding="{Binding LastName}" />
     <DataGridCheckBoxColumn Header="Fictitious?" Binding="{Binding IsFictitious}" />
  </DataGrid.Columns>
</DataGrid>

ViewModel

using AvaloniaControls.Models;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace AvaloniaControls.ViewModels
{
    public class MainWindowViewModel : ViewModelBase
    {
        public ObservableCollection<Person> People { get; }

        public MainWindowViewModel()
        {
            var people = new List<Person> 
            {
                new Person("Neil", "Armstrong", false),
                new Person("Buzz", "Lightyear", true),
                new Person("James", "Kirk", true)
            };
            People = new ObservableCollection<Person>(people);
        }
    }
}

数据源 Person 类

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public bool IsFictitious { get; set; }

    public Person(string firstName , string lastName, bool isFictitious)
    {
        FirstName = firstName;
        LastName = lastName;
        IsFictitious = isFictitious;
    }
}

数据表格模板列

您可以使用此列类型自定义数据网格列的显示和编辑。

有两个数据模板,您可以将其定义为附加属性:

数据模板 描述
CellTemplate 列值的显示(未编辑)呈现。
CellEditingTemplate 列值的编辑模板。

信息

如果您未设置编辑模板,该列将保持只读状态。

示例

此示例在编辑某人的年龄属性时添加一个数字上下控件:

<Window ...
  xmlns:model="using:AvaloniaControls.Models" >
  
  <DataGrid Margin="20" ItemsSource="{Binding People}"
          GridLinesVisibility="All"
          BorderThickness="1" BorderBrush="Gray">
    <DataGrid.Columns>
      <DataGridTextColumn Header="First Name" Width="2*"
         Binding="{Binding FirstName}" />
      <DataGridTextColumn Header="Last Name" Width="2*"
         Binding="{Binding LastName}" />
      
      <DataGridTemplateColumn Header="Age">
        <DataGridTemplateColumn.CellTemplate>
          <DataTemplate DataType="model:Person">
            <TextBlock Text="{Binding AgeInYears, StringFormat='{}{0} years'}" 
              VerticalAlignment="Center" HorizontalAlignment="Center" />
          </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
        <DataGridTemplateColumn.CellEditingTemplate>
          <DataTemplate DataType="model:Person">
            <NumericUpDown Value="{Binding AgeInYears}"  
               FormatString="N0" Minimum="0" Maximum="120"  
               HorizontalAlignment="Stretch"/>
          </DataTemplate>
        </DataGridTemplateColumn.CellEditingTemplate>
      </DataGridTemplateColumn>
    
    </DataGrid.Columns>
  </DataGrid>
</Window>

C# View Model

using AvaloniaControls.Models;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace AvaloniaControls.ViewModels
{
    public class MainWindowViewModel : ViewModelBase
    {
        public ObservableCollection<Person> People { get; }

        public MainWindowViewModel()
        {
            var people = new List<Person> 
            {
                new Person("Neil", "Armstrong",  55),
                new Person("Buzz", "Lightyear", 38),
                new Person("James", "Kirk", 44)
            };
            People = new ObservableCollection<Person>(people);
        }
    }
}

C# Item Class

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int AgeInYears { get; set; } 


    public Person(string firstName , string lastName, int ageInYears)
    {
        FirstName = firstName;
        LastName = lastName;
        AgeInYears = ageInYears;
    }
}

数据表格列

数据表格可以包含多个数据表格列,Avalonia UI 提供了两种内置列类型,用于显示不同的数据类型,还有一个可以自定义列外观的模板类型。

列类型 描述
DataGridTextColumn 用于显示和编辑列数据的文本框。您可以在此列类型中控制字体属性,比如字体家族和大小。
DataGridCheckBoxColumn 用于显示和编辑列数据的复选框,当数据类型为布尔值时。此列类型还支持当值为可空时的三态复选框。
DataGridTemplateColumn 可用于自定义列数据的展示和编辑。

常用属性

大部分属性在这三种列类型中都是通用的:

属性 描述
Header 列的标题内容。
HeaderTemplate 使用数据模板作为列的标题。
IsReadOnly 列是否为只读。如果数据表格本身是只读的,那么无论此属性的值如何,列都是只读的。
IsThreeState 仅适用于复选框列。当可空布尔值为null时,启用第三个(填充)状态。
Width 列宽度可以是绝对大小或相对大小(见下文)。

列宽度

如果您没有为列设置宽度,它将被调整以适应内容,并在必要时为网格添加水平滚动条。

您可以绝对设置列的宽度,例如:

<DataGridTextColumn Width="200" />

这将导致不适合的列内容被隐藏。

或者,您可以指定相对自动大小。这使用 * 表示可用宽度的等分,然后使用类似 2* 的倍数。未指定宽度的列将根据其内容调整大小。

例如,要将数据表格划分为3个等宽的列:

<DataGridTextColumn Width="*" />
<DataGridTextColumn Width="*" />
<DataGridTextColumn Width="*" />

示例

下面的示例通过将两列等宽展开来改进数据表格的外观:

<Window ... >
   <Design.DataContext>
       <vm:MainWindowViewModel/>
  </Design.DataContext>
  <DataGrid Margin="20" ItemsSource="{Binding People}"
          IsReadOnly="True"
          GridLinesVisibility="All"
          BorderThickness="1" BorderBrush="Gray">
    <DataGrid.Columns>
      <DataGridTextColumn Header="名字" Width="*" 
              Binding="{Binding FirstName}"/>
      <DataGridTextColumn Header="姓氏" Width="*" 
              Binding="{Binding LastName}" />
    </DataGrid.Columns>
  </DataGrid>
</Window>

C# ViewModel

using AvaloniaControls.Models;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace AvaloniaControls.ViewModels
{
    public class MainWindowViewModel : ViewModelBase
    {
        public ObservableCollection<Person> People { get; }

        public MainWindowViewModel()
        {
            var people = new List<Person> 
            {
                new Person("Neil", "Armstrong"),
                new Person("Buzz", "Lightyear"),
                new Person("James", "Kirk")
            };
            People = new ObservableCollection<Person>(people);
        }
    }
}

数据源 Person 类

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    
    public Person(string firstName , string lastName)
    {
        FirstName = firstName;
        LastName = lastName;
    }
}

在预览窗口中可以看到效果,因为 <Design.DataContext> 元素创建了绑定的 ViewModel:

DatePicker 日期选择器

日期选择器包含三个"轮盘"控制器,允许用户选择日期值。点击控件时会显示这些旋转器。

常用属性

你可能最常使用这些属性:

属性 描述
DayVisible 设置是否显示日列。
MonthVisible 设置是否显示月列。
YearVisible 设置是否显示年列。
DayFormat 日期中日部分的格式字符串。
MonthFormat 日期中月部分的格式字符串。
YearFormat 日期中年部分的格式字符串。
SelectedDate 选择的日期(无选择时为 null)。

示例

此示例使用日期格式属性来显示星期名及日期号:

<StackPanel Margin="20">
  <DatePicker DayFormat="ddd dd"/>
</StackPanel>

初始化日期

这个控件的日期属性不能在 XAML 中使用属性设置,因为没有可用的转换器来将字符串转换为日期对象,如 DateTimeDateTimeOffset

你需要编写如下 code-behind 代码:

datePicker.SelectedDate = new DateTimeOffset(new DateTime(1950, 1, 1));

Decorator 装饰器

Decorator 是用于装饰单个子控件的基础装饰器类。

参考资料

Decorator

源代码

Decorator.cs

DockPanel 边缘布局面板

边缘布局面板(Dock Panel)控件可以沿着指定的"停靠边缘"(顶部、底部、左侧和右侧)排列其子控件,最后一个子控件填充剩余的空间。边缘布局面板可以保持与停靠边缘平行的子控件尺寸,使得子控件沿停靠边缘填满所有可用空间。

例如,如果一个子控件的停靠边缘被定义为"顶部",并且它有一个定义的高度但没有宽度,它将会这样绘制:

注意

你必须定义与停靠边缘垂直的子控件尺寸,否则它将不会显示。

你可以选择性地定义与停靠边缘平行的尺寸。在这种情况下,子控件将根据同一方向上的对齐设置进行绘制。例如,一个定义了宽度并停靠在顶部边缘的子控件,将遵循其水平对齐属性(默认居中)。

子控件按照它们在XAML中定义的顺序进行停靠。当 Avalonia UI 正在调整子控件的大小时,会考虑到任何先前绘制的控件。这意味着永远不会有重叠。

最后定义的子控件将填满任何剩余的空间。

注意

你必须始终定义一个最后的子控件(没有停靠属性),否则停靠计算将无法正确进行。这意味着一个边缘布局面板需要至少两个子控件。

常用属性

你可能最常使用这些属性:

属性 描述
DockPanel.Dock.Left 附加到一个子控件 - 将其停靠在左侧。
DockPanel.Dock.Top 附加到一个子控件 - 将其停靠在顶部边缘。
DockPanel.Dock.Right 附加到一个子控件 - 将其停靠在右侧。
DockPanel.Dock.Bottom 附加到一个子控件 - 将其停靠在底部边缘。

示例

将橙色矩形的透明度设置为0.5,以证实图形间没有重叠。

<DockPanel Width="300" Height="300">
    <Rectangle Fill="Red" Height="100" DockPanel.Dock="Top"/>
    <Rectangle Fill="Blue" Width="100" DockPanel.Dock="Left" />
    <Rectangle Fill="Green" Height="100" DockPanel.Dock="Bottom"/>
    <Rectangle Fill="Orange" Width="100" DockPanel.Dock="Right" Opacity="0.5"/>
    <Rectangle Fill="Gray" />
</DockPanel>

Expander 折叠面板

折叠面板控件具有一个标题区域(始终可见)和一个可折叠的内容部分,该内容部分可以包含单个子控件。

常用属性

你可能最常使用这些属性:

属性 描述
Expander.Header 定义标题区域中显示的内容。

示例

<Expander VerticalAlignment="Top">
    <Expander.Header>
        隐藏搜索
    </Expander.Header>
    <Grid RowDefinitions="*,*" ColumnDefinitions="150,*">
        <TextBlock Grid.Row="0" Grid.Column="0"
                   VerticalAlignment="Center">搜索</TextBlock>
        <TextBox Grid.Row="0" Grid.Column="1"
                 Watermark="搜索文本" Width="200" />
        <TextBlock Grid.Row="1" Grid.Column="0"
                   VerticalAlignment="Center">区分大小写?</TextBlock>
        <CheckBox Grid.Row="1" Grid.Column="1" />
    </Grid>
</Expander>

Flyout 弹出层

弹出层是一种可关闭的容器,可以附加到某些类型的"宿主"控件上;尽管弹出层本身并不是控件。当宿主控件获得焦点时,弹出层会显示出来,并且可以通过多种不同的方式再次隐藏。

弹出层可以包含简单或更丰富的、组合的用户界面内容。

Avalonia UI 应用中,弹出层可以声明为资源,并在两个或更多宿主控件之间共享。

示例

通过宿主控件的 Flyout 属性附加弹出层。例如:

<Button Content="带弹出层的按钮">
  <Button.Flyout>
    <Flyout>这是按钮的弹出层</Flyout>
  </Button.Flyout>
</Button>

注意

只有按钮和分隔按钮控件支持 Flyout 属性。你可以使用 AttachedFlyout 属性将弹出层附加到其他 Avalonia UI 内置控件上。

对于没有 Flyout 属性的控件,使用 AttachedFlyout 属性如下:

<Border Background="Red" PointerPressed="Border_PointerPressed">
    <FlyoutBase.AttachedFlyout>
        <Flyout>
            <TextBlock Text="红色矩形弹出层" />
        </Flyout>
    </FlyoutBase.AttachedFlyout>
</Border>

弹出层不会自动显示,必须从 code-behind 显示。例如:

public void Border_PointerPressed(object sender, PointerPressedEventArgs args)
{
    var ctl = sender as Control;
    if (ctl != null)
    {
        FlyoutBase.ShowAttachedFlyout(ctl);
    }
}

常用属性

你可能最常使用这些属性:

属性 描述
Placement 弹出层相对于其附加控件的打开位置。
ShowMode 描述弹出层的显示和隐藏方式。请看下面的选项。

ShowMode

此设置描述弹出层的显示和隐藏方式:

模式 描述
Standard 当附加的控件获得焦点时显示弹出层。当附加的控件失去焦点时隐藏弹出层(用户切换焦点或点击其他地方)。
Transient 在弹出层外做出操作时(如点击)消失。
TransientWithDismiss OnPointerMoveAway 当光标移开一定距离后,弹出层自动消失。

所有弹出层的常用方法

属性 描述
ShowAt(Control) 在指定的目标控件上显示弹出层。
ShowAt(Control, bool) 在指定的目标控件上显示弹出层,但位置基于当前指针位置。
Hide 隐藏弹出层。

共享弹出层

你可以在应用中的两个或更多元素之间共享弹出层。例如,从窗口的资源集合中共享弹出层:

<Window.Resources>
    <Flyout x:Key="MySharedFlyout">
        <!-- 弹出层内容在此 -->
    </Flyout>
</Window.Resources>

<Button Content="点击我!" Flyout="{StaticResource MySharedFlyout}" />

<Button Content="现在点击我!" Flyout="{StaticResource MySharedFlyout}" />

弹出层的样式定制

虽然弹出层本身不是控件,但可以通过Flyout用来显示其内容的展示器来自定义其外观。对于普通的Flyout,这个展示器是FlyoutPresenter;对于MenuFlyout,则是MenuFlyoutPresenter。因为弹出层的展示器不是公开的,特定的弹出层相关的特殊样式类可以通过FlyoutBase上的FlyoutPresenterClasses属性传递:

<Style Selector="FlyoutPresenter.mySpecialClass">
    <Setter Property="Background" Value="Red" />
</Style>

<Flyout FlyoutPresenterClasses="mySpecialClass">
    <!-- 弹出层内容在此 -->
</Flyout>

Grid 网格布局

Grid 控件非常适用于按列和行排列子控件。您可以为 Grid 定义绝对大小、比例大小和自动大小的行和列几何形状。

每个位于 Grid 中的子控件都可以使用列和行坐标定位在 Grid 单元格中。这些坐标是从零开始的,并且默认值为零。

如果在同一单元格中定位多个子控件,它们将按照在 XAML 中出现的顺序在该单元格中绘制。这是实现层叠堆叠的另一种策略,除了使用 Panel

注意

如果您忽略了 Grid 的子控件的列和行坐标,它们都将被绘制在左上角(列=0,行=0)。

也可以使子控件跨越一个或多个单元格的行或列,或两者都跨越。

常用属性

您可能最常使用这些属性:

属性 描述
ColumnDefinitions Grid 中列宽的尺寸定义。
RowDefinitions Grid 中行高的尺寸定义。
ShowGridLines 显示单元格之间的网格线(作为虚线显示)。
Grid.Column 将控件布局到指定的从零开始的列中。
Grid.Row 将控件布局到指定的从零开始的行中。
Grid.ColumnSpan 将控件跨越一个或多个列。
Grid.RowSpan 将控件跨越一个或多个行。
Grid.IsSharedSizeScope 定义控件为 SharedSizeGroup 的包含范围。

尺寸定义

您可以如下定义行和列的大小:

  • 绝对大小 - 以设备独立像素(整数)为单位。
  • 比例大小 - 根据剩余 Grid 大小的比例。
  • 自动大小 - 根据包含的子控件的大小自动调整。

尺寸定义可以通过简短代码列表或使用 XAML 元素完全展开来编写。

完整定义支持额外的约束,如 SharedSizeGroup 和指定最小和最大长度的绝对大小。

绝对大小定义

绝对大小定义在列网格式中以整数形式编写。例如:

ColumnDefinitions="200, 200, 300"

通过完全展开的 XAML 定义,这与以下相同:

<Grid>
   <Grid.ColumnDefinitions>
       <ColumnDefinition Width="200"></ColumnDefinition>
       <ColumnDefinition Width="200"></ColumnDefinition>
       <ColumnDefinition Width="300"></ColumnDefinition>
   </Grid.ColumnDefinitions>
</Grid>

比例大小定义

比例大小定义使用星号表示可用 Grid 空间的比例。例如,要创建两个宽度相同的列,然后是一个宽度是前两个的两倍(单个宽度的两倍)的列:

ColumnDefinitions="*, *, 2*"

通过完全展开的 XAML 定义,这与以下相同:

<Grid>
   <Grid.ColumnDefinitions>
       <ColumnDefinition Width="*"></ColumnDefinition>
       <ColumnDefinition Width="*"></ColumnDefinition>
       <ColumnDefinition Width="2*"></ColumnDefinition>
   </Grid.ColumnDefinitions>
</Grid>

提示

尺寸定义不支持百分比。一个解决方法是创建一个定义,其中所有比例值加起来等于 100,例如 <Grid ColumnDefinitions="25*, 25*, 50*"> 用于 3 个列,每个列分别占剩余可用宽度的 25%、25% 和 50%。

自动大小定义

要自动调整行或列的大小以适应其中最大的子控件,请使用 'Auto' 代码。例如:

RowDefinitions="Auto, Auto, Auto"

通过完全展开的 XAML 定义下相同:,这与以

<Grid>
   <Grid.RowDefinitions>
       <RowDefinition Height="Auto"></RowDefinition>
       <RowDefinition Height="Auto"></RowDefinition>
       <RowDefinition Height="Auto"></RowDefinition>
   </Grid.RowDefinitions>
</Grid>

注意

如果子控件有自己显式设置的尺寸,当绘制时将遵循这些尺寸。这意味着如果它大于其网格单元格,它将重叠相邻的单元格。

混合尺寸定义

您可以在同一尺寸定义序列中混合使用上述任何一种。例如:

ColumnDefinitions="200, *, 2*"

通过完全展开的 XAML 定义,这与以下相同:

<Grid>
   <Grid.ColumnDefinitions>
       <ColumnDefinition Width="200"></ColumnDefinition>
       <ColumnDefinition Width="*"></ColumnDefinition>
       <ColumnDefinition Width="2*"></ColumnDefinition>
   </Grid.ColumnDefinitions>
</Grid>

绘图规则

在计算尺寸时,任何比例列都将适应在计算绝对值和自动值后剩余的空间。

自动尺寸的计算是使用子控件的边距布局区域外缘进行的。

信息

要回顾控制布局区域的概念,请参阅此处

子控件按照它们在 XAML 中出现的顺序在其分配的网格单元格中绘制。这条规则既适用于当两个子控件被分配到同一单元格时的情况,也适用于子控件大于其分配单元格时的重叠情况。

当子控件有自己的尺寸,并且小于其分配的单元格时,它将根据其水平和垂直对齐属性(默认都是居中)在单元格中对齐绘制。

示例

这个示例展示了:

  • 如何使用简短语法定义列和行。
  • 如何混合绝对和比例列宽。
  • 如何为子控件分配单元格。
  • 如何跨行和列。

一个包含 3 个相等行和 3 列(1 个固定宽度),(2 个按比例抓取剩余宽度)的 Grid 的示例是:

<Grid ColumnDefinitions="100,1.5*,4*" RowDefinitions="Auto,Auto,Auto"  Margin="4">
  <TextBlock Text="Col0Row0:" Grid.Row="0" Grid.Column="0"/>
  <TextBlock Text="Col0Row1:" Grid.Row="1" Grid.Column="0"/>
  <TextBlock Text="Col0Row2:" Grid.Row="2" Grid.Column="0"/>
  <CheckBox Content="Col2Row0" Grid.Row="0" Grid.Column="2"/>
  <Button Content="SpansCol1-2Row1-2" Grid.Row="1" Grid.Column="1" Grid.RowSpan="2" Grid.ColumnSpan="2"/>
</Grid>

在这里,100 的绝对宽度被减去后(对于列 0),列 1 将获得 1.5 个部分,列 2 将获得剩余宽度的 4 个部分。

按钮被绘制以填充从单元格(列 1,行 1)加一个列(向右)和一行向下的跨度。结果看起来是这样的:

SharedSizeGroup

SharedSizeGroup 允许在多个 Grid 控件之间共享自动调整大小的行和列定义的大小信息。

示例

以下示例演示了如何使用 SharedSizeGroupListBox 内外一致地调整列的大小。

  • XML

  • C#

    <StackPanel Grid.IsSharedSizeScope="True"> <StackPanel.Styles> <Style Selector="ListBoxItem"> <Setter Property="Padding" Value="0" /> </Style> </StackPanel.Styles>
    <ListBox ItemsSource="{Binding People}">
      <ListBox.ItemTemplate>
        <DataTemplate>
          <Grid Name="myGrid" RowDefinitions="auto, auto" ShowGridLines="True">
            <Grid.ColumnDefinitions>
              <ColumnDefinition SharedSizeGroup="A" />
              <ColumnDefinition SharedSizeGroup="B" />
              <ColumnDefinition Width="*" />
              <ColumnDefinition SharedSizeGroup="C" />
            </Grid.ColumnDefinitions>
    
            <TextBlock Grid.Column="0" Margin="6,0" Text="{Binding FirstName}" />
            <TextBlock Grid.Column="1" Margin="6,0" Text="{Binding LastName}" />
            <TextBlock Grid.Column="2" Margin="6,0" Text="{Binding Age}" />
            <TextBlock Grid.Column="3" Margin="6,0" Text="{Binding Occupation}" />
          </Grid>
        </DataTemplate>
      </ListBox.ItemTemplate>
    </ListBox>
      
    <!-- Controls may appear in-between Grids with SharedSizeGroups -->
    <Separator />
    
    <Grid>
      <Grid.ColumnDefinitions>
        <ColumnDefinition SharedSizeGroup="A" />
        <ColumnDefinition SharedSizeGroup="B" />
        <ColumnDefinition Width="*" />
        <ColumnDefinition SharedSizeGroup="C" />
      </Grid.ColumnDefinitions>
    
      <Button Content="This is the First Name" HorizontalAlignment="Stretch" Grid.Column="0" />
      <Button Content="Last" HorizontalAlignment="Stretch" Grid.Column="1" />
      <Button Content="Age" HorizontalAlignment="Stretch" Grid.Column="2" />
      <Button Content="Occupation" HorizontalAlignment="Stretch" Grid.Column="3" />
    </Grid>
    
    </StackPanel>

请注意每列的大小:第一列由 Button 调整大小,第二列和第四列由 ListBox 内容调整大小,第三列占用剩余空间。

GridSplitter 网格分割器

网格分割器控件允许用户在运行时调整网格中的列或行的大小。分割器被绘制为一列或一行(可以指定大小),并具有一个用户可以在运行时操作的把手。

常用属性

你可能最常使用这些属性:

属性 描述
Background 分割条的背景颜色。
Grid.Column 附加属性,用来指定分割器的列位置。
Grid.Row 附加属性,用来指定分割器的行位置。
ResizeDirection 分割器的移动方向。(见下面的注释)

注意

为了提供任何有意义的移动,分割器的移动方向必须与其位置定义相同。即:对于列分割器指定 ResizeDirection="Columns",对于行分割器指定 ResizeDirection="Rows"

示例

这是一个列分割器:

<Grid ColumnDefinitions="*, 4, *">
    <Rectangle Grid.Column="0" Fill="Blue"/>
    <GridSplitter Grid.Column="1" Background="Black" ResizeDirection="Columns"/>
    <Rectangle Grid.Column="2" Fill="Red"/>
</Grid>

这是一个行分割器:

<Grid RowDefinitions="*, 4, *">
    <Rectangle Grid.Row="0" Fill="Blue"/>
    <GridSplitter Grid.Row="1" Background="Black" ResizeDirection="Rows"/>
    <Rectangle Grid.Row="2" Fill="Red"/>
</Grid>

Image 图像

图像可以从指定的图像源显示栅格图像。源可以是:

  • 一个字符串常量,对应一个应用程序资源,
  • 从资源的绑定名称加载为位图(通过使用绑定转换器),
  • 或者可以直接从内存流加载为位图。

图像可以用来组成其他控件的内容。例如,您可以使用图像控件创建一个图形按钮。

显示的图像可以被调整大小和缩放。默认的缩放设置(两个方向上均匀拉伸)将导致图像适应给定的大小(宽度和/或高度)。

信息

图像的缩放设置与视图框的相同,参见ViewBox

示例

此示例展示了一个位图资源被加载到图像控件中,其中高度和宽度被限制,但缩放设置保持默认。图像本身不是正方形,但图像的宽度和高度设置为相同的值。包括矩形是为了给出图像被缩放的一个概念:

<Panel>
  <Rectangle Height="300" Width="300" Fill="LightGray"/>
  <Image Margin="20" Height="200" Width="200" 
         Source="avares://AvaloniaControls/Assets/pipes.jpg"/>
</Panel>

在下一个示例中,引入了 UniformToFill 的拉伸设置,使得图像完全填满指定的高度,但会裁剪掉超出指定宽度的部分。图像没有因此处理而失真。

<Panel>
  <Rectangle Height="300" Width="300" Fill="LightGray"></Rectangle>
  <Image Margin="20" Height="200" Width="200" 
         Stretch="UniformToFill"
         Source="avares://AvaloniaControls/Assets/pipes.jpg"/>
</Panel>

ItemsControl 元素集合控件

元素集合控件是用于显示重复数据的控件(例如列表框)的基础。它本身不包含内置的格式化或交互功能;但你可以结合数据绑定、样式和数据模板使用,创建一个完全自定义的重复数据控件。

信息

要查看 Avalonia UI 内置的所有重复数据控件的完整列表,请查看这里

常用属性

你可能最常使用这些属性:

属性 描述
ItemsSource 用作控件数据源的绑定集合。
ItemsControl.ItemTemplate 附加属性元素,包含单个元素的数据模板。

示例

此示例将一个可观察的餐具项集合绑定到一个元素控件,其中通过数据模板提供了一些自定义布局和格式化:

<StackPanel Margin="20">
  <TextBlock Margin="0 5">餐具列表:</TextBlock>
  <ItemsControl ItemsSource="{Binding CrockeryList}" >
    <ItemsControl.ItemTemplate>
    <DataTemplate>
      <Border Margin="0,10,0,0"
          CornerRadius="5"
          BorderBrush="Gray" BorderThickness="1"
          Padding="5">
        <StackPanel Orientation="Horizontal">
          <TextBlock Text="{Binding Title}"/>
          <TextBlock Margin="5 0" FontWeight="Bold" 
                      Text="{Binding Number}"/>
        </StackPanel>
      </Border>
    </DataTemplate>
    </ItemsControl.ItemTemplate>
    </ItemsControl>
</StackPanel>

C# ViewModel

using AvaloniaControls.Models;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace AvaloniaControls.ViewModels
{
    public class MainWindowViewModel : ViewModelBase
    {
        public ObservableCollection<Crockery> CrockeryList { get; set; }
        
        public MainWindowViewModel()
        {
            CrockeryList = new ObservableCollection<Crockery>(new List<Crockery>
            {
                new Crockery("晚餐盘", 12),
                new Crockery("小碟", 12),
                new Crockery("早餐碗", 6),
                new Crockery("杯子", 10),
                new Crockery("茶碟", 10),
                new Crockery("马克杯", 6),
                new Crockery("牛奶壶", 1)
            });    
        }
    }
}

C# 数据源的类定义

public class Crockery
{
    public string Title { get; set; }
    public int Number{ get; set; }

    public Crockery(string title, int number)
    {
        Title = title;
        Number = number;
    }
}

视图水平方向可调整大小,但内容在过高时会被隐藏。这个控件没有内置滚动条(与 ListBox 不同)。

ItemsRepeater 元素重复器

元素重复器可以从绑定的数据源显示重复数据。它具有布局模板和数据模板。

信息

元素重复器是 UWP ItemsRepeater 控件的移植版本。更多信息请参见这里

信息

元素重复器已移至这里

默认的布局模板是垂直堆叠布局,因此元素会以垂直列表的形式显示。

示例

此示例将一个可观察的餐具项集合绑定到元素重复器控件,其中每个元素的自定义布局和格式由数据模板提供:

<StackPanel Margin="20">
  <TextBlock Margin="0 5">餐具列表:</TextBlock>
  <ItemsRepeater ItemsSource="{Binding CrockeryList}">
    <ItemsRepeater.ItemTemplate>
      <DataTemplate>
        <Border Margin="0,10,0,0"
            CornerRadius="5"
            BorderBrush="Blue" BorderThickness="1"
            Padding="5">
          <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding Title}"/>
            <TextBlock Margin="5 0" FontWeight="Bold" 
                        Text="{Binding Number}"/>
          </StackPanel>
        </Border>
      </DataTemplate>
    </ItemsRepeater.ItemTemplate>
  </ItemsRepeater>
</StackPanel>

C# ViewModel

using AvaloniaControls.Models;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace AvaloniaControls.ViewModels
{
    public class MainWindowViewModel : ViewModelBase
    {
        public ObservableCollection<Crockery> CrockeryList { get; set; }
        
        public MainWindowViewModel()
        {
            CrockeryList = new ObservableCollection<Crockery>(new List<Crockery>
            {
                new Crockery("晚餐盘", 12),
                new Crockery("小盘", 12),
                new Crockery("早餐碗", 6),
                new Crockery("杯子", 10),
                new Crockery("茶托", 10),
                new Crockery("马克杯", 6),
                new Crockery("牛奶壶", 1)
            });    
        }
    }
}

C# 数据源的类定义

public class Crockery
{
    public string Title { get; set; }
    public int Number { get; set; }

    public Crockery(string title, int number)
    {
        Title = title;
        Number = number;
    }
}

默认情况下,元素重复器将以垂直堆叠布局渲染元素。你可以通过使用 <ItemsRepeater.Layout> 元素覆盖此设置,使元素水平显示。例如:

<StackPanel Margin="20">
  <TextBlock Margin="0 5">餐具列表:</TextBlock>
  <ScrollViewer HorizontalScrollBarVisibility="Auto">
    <ItemsRepeater ItemsSource="{Binding CrockeryList}" Margin="0 20">
      <ItemsRepeater.Layout>
        <StackLayout Spacing="40"
            Orientation="Horizontal" />
      </ItemsRepeater.Layout>
      <ItemsRepeater.ItemTemplate>
        <DataTemplate>
          <Border Margin="0,10,0,0"
              CornerRadius="5"
              BorderBrush="Blue" BorderThickness="1"
              Padding="5">
            <StackPanel Orientation="Horizontal">
              <TextBlock Text="{Binding Title}"/>
              <TextBlock Margin="5 0" FontWeight="Bold" 
                          Text="{Binding Number}"/>
            </StackPanel>
          </Border>
        </DataTemplate>
      </ItemsRepeater.ItemTemplate>
    </ItemsRepeater>
  </ScrollViewer>
</StackPanel>

元素水平显示,如果没有添加围绕元素重复器的滚动查看器元素,那么过于靠右的元素将会被隐藏。

相关推荐
IT猿手17 分钟前
多目标优化算法:多目标鹅算法(MOGOOSE)求解UF1-UF10,提供完整MATLAB代码
开发语言·算法·matlab·多目标算法
水w19 分钟前
VuePress v2 快速搭建属于自己的个人博客网站
开发语言·前端·vue·vuepress
羊小猪~~1 小时前
前端入门一之ES6--递归、浅拷贝与深拷贝、正则表达式、es6、解构赋值、箭头函数、剩余参数、String、Set
开发语言·前端·javascript·css·正则表达式·html·es6
932我2 小时前
C++中的组合模式
开发语言·c++·组合模式
IT规划师3 小时前
开源 - Ideal库 - 枚举扩展设计思路及实现难点(三)
开源·c#·.net core·ideal库·枚举转换
MrJson-架构师3 小时前
java 操作Mongodb
java·开发语言·mongodb
红中马喽3 小时前
JS学习日记(jQuery库)
开发语言·javascript·笔记·学习·jquery
橘子真甜~3 小时前
9.C++面向对象6(实现一个较为完善的日期类)
开发语言·c++
这将会是一个好名字3 小时前
Mac上详细配置java开发环境和软件(更新中)
java·开发语言·macos