WPF 入门教程DataGrid基本功能

当使用 GridView 时,DataGrid 控件看起来很像 ListView,但它提供了许多附加功能。例如,DataGrid可以根据您提供给它的数据自动生成列。默认情况下,DataGrid也是可编辑的,允许最终用户更改基础数据源的值。

DataGrid最常见的用法是与数据库结合使用,但与大多数WPF控件一样,它与内存中的源(如对象列表)同样适用。由于演示起来容易得多,我们将在本教程中主要使用后一种方法。

简单的DataGrid

您可以在不设置任何属性的情况下开始使用DataGrid,因为它支持很多开箱即用的功能。在第一个示例中,我们将这样做,然后分配我们自己的User对象列表作为项目源:

<Window x:Class="WpfTutorialSamples.DataGrid_control.SimpleDataGridSample"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="SimpleDataGridSample" Height="180" Width="300">
    <Grid Margin="10">
        <DataGrid Name="dgSimple"></DataGrid>
    </Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Windows;

namespace WpfTutorialSamples.DataGrid_control
{
    public partial class SimpleDataGridSample : Window
    {
        public SimpleDataGridSample()
        {
            InitializeComponent();

            List<User> users = new List<User>();
            users.Add(new User() { Id = 1, Name = "John Doe", Birthday = new DateTime(1971, 7, 23) });
            users.Add(new User() { Id = 2, Name = "Jane Doe", Birthday = new DateTime(1974, 1, 17) });
            users.Add(new User() { Id = 3, Name = "Sammy Doe", Birthday = new DateTime(1991, 9, 2) });

            dgSimple.ItemsSource = users;
        }
    }

    public class User
    {
        public int Id { get; set; }

        public string Name { get; set; }

        public DateTime Birthday { get; set; }
    }
}

这就是开始使用 DataGrid 所需的全部内容。源可以很容易地是一个数据库表/视图,甚至是一个 XML 文件 - DataGrid 并不挑剔它从哪里获取数据。

如果您在其中一个单元格内单击,您会看到默认情况下您可以编辑每个属性。作为一个不错的小奖励,您可以尝试单击其中一个列标题 - 您将看到DataGrid支持开箱即用的排序!

最后一个空行将让您添加到数据源,只需填写单元格即可。

我们了解了启动和运行 WPF DataGrid是多么容易。它如此简单的原因之一是DataGrid会根据您使用的数据源自动为您生成适当的列。

但是,在某些情况下,您可能想要手动定义显示的列,因为您不想要数据源的所有属性/列,或者因为您想要控制使用哪些内联编辑器。

手动定义的列

让我们尝试一个看起来很像前一章中的示例,但我们手动定义所有列,以实现最大控制。您可以根据要显示/编辑的数据选择列类型。在撰写本文时,可以使用以下列类型:

  • DataGridTextColumn
  • DataGridCheckBoxColumn
  • DataGridComboBoxColumn
  • DataGridHyperlinkColumn
  • DataGridTemplateColumn

尤其是最后一个DataGridTemplateColumn很有趣。它允许您定义任何类型的内容,这为使用来自 WPF 库甚至您自己或第三方控件的自定义控件提供了机会。下面是一个例子:

<Window x:Class="WpfTutorialSamples.DataGrid_control.DataGridColumnsSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="DataGridColumnsSample" Height="200" Width="300">
    <Grid Margin="10">
		<DataGrid Name="dgUsers" AutoGenerateColumns="False">
			<DataGrid.Columns>

				<DataGridTextColumn Header="Name" Binding="{Binding Name}" />

				<DataGridTemplateColumn Header="Birthday">
					<DataGridTemplateColumn.CellTemplate>
						<DataTemplate>
							<DatePicker SelectedDate="{Binding Birthday}" BorderThickness="0" />
						</DataTemplate>
					</DataGridTemplateColumn.CellTemplate>
				</DataGridTemplateColumn>

			</DataGrid.Columns>
		</DataGrid>
	</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Windows;

namespace WpfTutorialSamples.DataGrid_control
{
	public partial class DataGridColumnsSample : Window
	{
		public DataGridColumnsSample()
		{
			InitializeComponent();

			List<User> users = new List<User>();
			users.Add(new User() { Id = 1, Name = "John Doe", Birthday = new DateTime(1971, 7, 23) });
			users.Add(new User() { Id = 2, Name = "Jane Doe", Birthday = new DateTime(1974, 1, 17) });
			users.Add(new User() { Id = 3, Name = "Sammy Doe", Birthday = new DateTime(1991, 9, 2) });

			dgUsers.ItemsSource = users;
		}
	}

	public class User
	{
		public int Id { get; set; }

		public string Name { get; set; }

		public DateTime Birthday { get; set; }
	}
}

在标记中,我在DataGrid 上添加了AutoGenerateColumns属性,我已将其设置为false,以控制所使用的列。如您所见,我忽略了 ID 列,因为我决定在此示例中不关心它。对于 Name 属性,我使用了一个简单的基于文本的列,因此本示例中最有趣的部分来自生日列,其中我使用了一个DataGridTemplateColumn,其中包含一个 DatePicker控件。这允许最终用户从日历中选择日期,而不必手动输入它,如屏幕截图所示。

带有行详细信息的DataGrid

使用 DataGrid 控件时一个非常常见的使用场景是能够显示每行的详细信息,通常就在行本身的正下方。WPF DataGrid 控件很好地支持了这一点,幸运的是它也非常易于使用。让我们从一个例子开始,然后我们将讨论它是如何工作的以及它为您提供的选项:

<Window x:Class="WpfTutorialSamples.DataGrid_control.DataGridDetailsSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="DataGridDetailsSample" Height="200" Width="400">
	<Grid Margin="10">
		<DataGrid Name="dgUsers" AutoGenerateColumns="False">
			<DataGrid.Columns>
				<DataGridTextColumn Header="Name" Binding="{Binding Name}" />
				<DataGridTextColumn Header="Birthday" Binding="{Binding Birthday}" />
			</DataGrid.Columns>
			<DataGrid.RowDetailsTemplate>
				<DataTemplate>
					<TextBlock Text="{Binding Details}" Margin="10" />
				</DataTemplate>
			</DataGrid.RowDetailsTemplate>
		</DataGrid>
	</Grid>
</Window>


using System;
using System.Collections.Generic;
using System.Windows;

namespace WpfTutorialSamples.DataGrid_control
{
	public partial class DataGridDetailsSample : Window
	{
		public DataGridDetailsSample()
		{
			InitializeComponent();
			List<User> users = new List<User>();
			users.Add(new User() { Id = 1, Name = "John Doe", Birthday = new DateTime(1971, 7, 23) });
			users.Add(new User() { Id = 2, Name = "Jane Doe", Birthday = new DateTime(1974, 1, 17) });
			users.Add(new User() { Id = 3, Name = "Sammy Doe", Birthday = new DateTime(1991, 9, 2) });

			dgUsers.ItemsSource = users;
		}
	}

	public class User
	{
		public int Id { get; set; }

		public string Name { get; set; }

		public DateTime Birthday { get; set; }

		public string Details
		{
			get
			{
				return String.Format("{0} was born on {1} and this is a long description of the person.", this.Name, this.Birthday.ToLongDateString());
			}
		}
	}
}

如您所见,我扩展了前几章的示例,在 User 类上添加了一个新属性:Description 属性。对于我们的详细信息行,它只是返回有关相关用户的一些信息。

在标记中,我定义了几列,然后使用RowDetailsTemplate为行详细信息指定模板。如您所见,它的工作方式与任何其他 WPF 模板非常相似,其中我使用一个 DataTemplate,其中包含一个或多个控件,以及针对数据源上的属性(在本例中为 Description 属性)的标准绑定。

正如您从生成的屏幕截图中看到的,或者如果您自己运行示例,详细信息现在显示在所选行下方。选择另一行后,将显示该行的详细信息,而隐藏先前选择的行的详细信息。

控制行详细信息可见性

使用RowDetailsVisibilityMode属性,您可以更改上述行为。它默认为VisibleWhenSelected,其中详细信息仅在其父行被选中时可见,但您可以将其更改为VisibleCollapsed。如果将其设置为 Visible,则所有详细信息行将始终可见,如下所示:

如果您将其设置为已折叠,则所有详细信息将始终不可见。

更多细节

本文的第一个示例可能有点乏味,只使用了一个简单的TextBlock控件。当然,由于这是一个DataTemplate,你几乎可以做任何你想做的事情,所以我决定稍微扩展这个例子,以更好地了解可能性。这是它现在的样子:

正如您从代码清单中看到的,它主要是将详细信息模板扩展为使用面板,而面板又可以承载更多面板和/或控件。使用Grid面板,我们可以获得用户数据的表格外观,而 Image 控件允许我们显示用户的图片(您最好从本地资源而不是远程资源加载它,就像我在例如 - 很抱歉我懒得找到 Jane和Sammy Doe的匹配图像)。

<Window x:Class="WpfTutorialSamples.DataGrid_control.DataGridDetailsSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="DataGridDetailsSample" Height="300" Width="300">
	<Grid Margin="10">
		<DataGrid Name="dgUsers" AutoGenerateColumns="False">
			<DataGrid.Columns>
				<DataGridTextColumn Header="Name" Binding="{Binding Name}" />
				<DataGridTextColumn Header="Birthday" Binding="{Binding Birthday}" />
			</DataGrid.Columns>
			<DataGrid.RowDetailsTemplate>
				<DataTemplate>
					<DockPanel Background="GhostWhite">
						<Image DockPanel.Dock="Left" Source="{Binding ImageUrl}" Height="64" Margin="10" />
						<Grid Margin="0,10">
							<Grid.ColumnDefinitions>
								<ColumnDefinition Width="Auto" />
								<ColumnDefinition Width="*" />
							</Grid.ColumnDefinitions>
							<Grid.RowDefinitions>
								<RowDefinition Height="Auto" />
								<RowDefinition Height="Auto" />
								<RowDefinition Height="Auto" />
							</Grid.RowDefinitions>

							<TextBlock Text="ID: " FontWeight="Bold" />
							<TextBlock Text="{Binding Id}" Grid.Column="1" />
							<TextBlock Text="Name: " FontWeight="Bold" Grid.Row="1" />
							<TextBlock Text="{Binding Name}" Grid.Column="1" Grid.Row="1" />
							<TextBlock Text="Birthday: " FontWeight="Bold" Grid.Row="2" />
							<TextBlock Text="{Binding Birthday, StringFormat=d}" Grid.Column="1" Grid.Row="2" />

						</Grid>
					</DockPanel>
				</DataTemplate>
			</DataGrid.RowDetailsTemplate>
		</DataGrid>
	</Grid>
</Window>


using System;
using System.Collections.Generic;
using System.Windows;

namespace WpfTutorialSamples.DataGrid_control
{
	public partial class DataGridDetailsSample : Window
	{
		public DataGridDetailsSample()
		{
			InitializeComponent();
			List<User> users = new List<User>();
			users.Add(new User() { Id = 1, Name = "John Doe", Birthday = new DateTime(1971, 7, 23), ImageUrl = "http://www.wpf-tutorial.com/images/misc/john_doe.jpg" });
			users.Add(new User() { Id = 2, Name = "Jane Doe", Birthday = new DateTime(1974, 1, 17) });
			users.Add(new User() { Id = 3, Name = "Sammy Doe", Birthday = new DateTime(1991, 9, 2) });

			dgUsers.ItemsSource = users;
		}
	}

	public class User
	{
		public int Id { get; set; }

		public string Name { get; set; }

		public DateTime Birthday { get; set; }

		public string ImageUrl { get; set; }
	}
}

推荐一款WPF MVVM框架开源项目:Newbeecoder.UI

https://www.zhihu.com/video/1504808415512104960

Demo下载:

编辑于 2022-05-03 13:05