在本教程中您将学习如何在代码中为网格控件创建数据源,还将看到如何应用数据属性使网格应用适当的编辑模式、单元格编辑器和输入验证规则。
P.S:DevExpress WinForms拥有180+组件和UI库,能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForms能完美构建流畅、美观且易于使用的应用程序,无论是Office风格的界面,还是分析处理大批量的业务数据,它都能轻松胜任!
获取DevExpress WinForms v24.1正式版下载
DevExpress技术交流群11:749942875 欢迎一起进群讨论
使用DevExpress项目向导创建一个简单的数据源
在创建新解决方案时,首先使用DevExpress模板集合中的DevExpress Project Wizard(项目向导)创建一个项目。
启动应用程序,看到网格显示了样本数据。
切换到代码来定位此数据的来源,向导会自动生成代码,包括表单构造函数中的InitGrid方法调用。该方法使用Person类的5个实例填充BindingList,然后将BindingList对象分配给网格控件的GridControl.DataSource属性。
C#
class Person { string firstName; string secondName; string comments; public Person(string firstName, string secondName) { this.firstName = firstName; this.secondName = secondName; comments = String.Empty; } public Person(string firstName, string secondName, string comments) : this(firstName, secondName) { this.comments = comments; } public string FirstName { get { return firstName; } set { firstName = value; } } public string SecondName { get { return secondName; } set { secondName = value; } } public string Comments { get { return comments; } set { comments = value; } } } public Form1() { // ... InitGrid(); } BindingList<Person> gridDataList = new BindingList<Person>(); void InitGrid() { gridDataList.Add(new Person("John", "Smith")); gridDataList.Add(new Person("Gabriel", "Smith")); gridDataList.Add(new Person("Ashley", "Smith", "some comment")); gridDataList.Add(new Person("Adrian", "Smith", "some comment")); gridDataList.Add(new Person("Gabriella", "Smith", "some comment")); gridControl.DataSource = gridDataList; }
VB.NET
Friend Class Person Private firstName_Renamed As String Private secondName_Renamed As String Private comments_Renamed As String Public Sub New(ByVal firstName As String, ByVal secondName As String) Me.firstName_Renamed = firstName Me.secondName_Renamed = secondName comments_Renamed = String.Empty End Sub Public Sub New(ByVal firstName As String, ByVal secondName As String, ByVal comments As String) Me.New(firstName, secondName) Me.comments_Renamed = comments End Sub Public Property FirstName() As String Get Return firstName_Renamed End Get Set(ByVal value As String) firstName_Renamed = value End Set End Property Public Property SecondName() As String Get Return secondName_Renamed End Get Set(ByVal value As String) secondName_Renamed = value End Set End Property Public Property Comments() As String Get Return comments_Renamed End Get Set(ByVal value As String) comments_Renamed = value End Set End Property End Class Public Sub New() ' ... InitGrid() End Sub Private gridDataList As New BindingList(Of Person)() Private Sub InitGrid() gridDataList.Add(New Person("John", "Smith")) gridDataList.Add(New Person("Gabriel", "Smith")) gridDataList.Add(New Person("Ashley", "Smith", "some comment")) gridDataList.Add(New Person("Adrian", "Smith", "some comment")) gridDataList.Add(New Person("Gabriella", "Smith", "some comment")) gridControl.DataSource = gridDataList End Sub
在最简单的情况下,这就是如何在代码中创建数据。定义一个表示记录的对象,然后创建这样一个对象的集合,并将该集合分配给网格的GridControl.DataSource属性。
创建更复杂的数据源
现在来看几个用代码创建数据并将其绑定到网格的示例。
您可以定义作为数据记录的自定义类,本教程中的示例代码文件包含3个类的定义:CompanyPublicInfo、CompanyPrivateInfo和Product,每个类都包含自己的属性,这些属性将用作数据字段。
C#
// ... public class CompanyPublicInfo { public string CompanyName { get; set; } public string Country { get; set; } public string City { get; set; } public string Url { get; set; } public string Email { get; set; } public string Phone { get; set; } public string AdditionalInfo { get; set; } } // ...
VB.NET
Public Class CompanyPublicInfo Public Property CompanyName() As String Public Property Country() As String Public Property City() As String Public Property Url() As String Public Property Email() As String Public Property Phone() As String Public Property AdditionalInfo() As String End Class
这个文件后面定义的GridSampleDataList类提供了3个方法:GetCompanyPrivateInfo、GetCompanyPublicInfo和GetProductSample,这些方法中的每一个都返回一个由相应类的对象填充的BindingList:
C#
public class GridSampleDataList { static public List<CompanyPublicInfo> GetCompanyPublicInfo() { return new List<CompanyPublicInfo> { new CompanyPublicInfo() { AdditionalInfo = "Some Info", City = "Glendale", CompanyName = "Developer Express", Country = "USA", Email = "[email protected]", Phone = "1234567890", Url = "www.devexpress.com", }, // ... }; } // ... }
VB.NET
Public Class GridSampleDataList Public Shared Function GetCompanyPublicInfo() As List(Of CompanyPublicInfo) Return New List(Of CompanyPublicInfo) From { New CompanyPublicInfo() With { .AdditionalInfo = "Some Info", .City = "Glendale", .CompanyName = "Developer Express", .Country = "USA", .Email = "[email protected]", .Phone = "1234567890", .Url = "www.devexpress.com" } } End Function ' ... End Class
现在创建允许应用程序用户在这三个数据源之间切换的UI,返回到主表单设计,您可以看到添加到Ribbon Control的编辑器,下拉列表将包含三个与前面定义的数据源类型相对应的项。
现在处理BarEditItem.EditValueChanged事件,根据当前选择的下拉列表项将不同的BindingList对象分配给网格的GridControl.DataSource 。
C#
private void barEditItem1_EditValueChanged(object sender, EventArgs e) { DevExpress.XtraBars.BarEditItem item = sender as DevExpress.XtraBars.BarEditItem; if(item == null) return; switch (item.EditValue as string) { case "Company public info": gridControl.DataSource = GridSampleDataList.GetCompanyPublicInfo(); break; case "Company private info": gridControl.DataSource = GridSampleDataList.GetCompanyPrivateInfo(); break; case "Product info": gridControl.DataSource = GridSampleDataList.GetProductSample(); break; } }
VB.NET
Private Sub barEditItem1_EditValueChanged(ByVal sender As Object, ByVal e As EventArgs) Dim item As DevExpress.XtraBars.BarEditItem = TryCast(sender, DevExpress.XtraBars.BarEditItem) If item Is Nothing Then Return End If Select Case TryCast(item.EditValue, String) Case "Company public info" gridControl.DataSource = GridSampleDataList.GetCompanyPublicInfo() Case "Company private info" gridControl.DataSource = GridSampleDataList.GetCompanyPrivateInfo() Case "Product info" gridControl.DataSource = GridSampleDataList.GetProductSample() End Select End Sub
要确保基于当前可用的数据字段重新创建网格列,请处理GridControl.DataSourceChanged事件,该事件在网格每次接收到新数据源时触发。在事件处理程序中,只需调用ColumnView.PopulateColumns 方法即可完成所需的工作。
C#
void gridControl_DataSourceChanged(object sender, EventArgs e) { DevExpress.XtraGrid.GridControl grid = sender as DevExpress.XtraGrid.GridControl; if(grid == null) return; grid.MainView.PopulateColumns(); (grid.MainView as GridView).BestFitColumns(); }
VB.NET
Private Sub gridControl_DataSourceChanged(ByVal sender As Object, ByVal e As EventArgs) Dim grid As DevExpress.XtraGrid.GridControl = TryCast(sender, DevExpress.XtraGrid.GridControl) If grid Is Nothing Then Return End If grid.MainView.PopulateColumns() TryCast(grid.MainView, GridView).BestFitColumns() End Sub
运行应用程序,看看它是如何工作的,应用程序仍然以自动生成的样例数据启动。如果您从Ribbon中的下拉列表中选择一个项目,网格将显示来自相应数据源的数据。
应用数据标注属性
请注意,所有网格列都显示了其默认编辑器,并应用了默认格式。例如,Product Info数据包含不能完全查看的多行文本,因为默认的网格单元格编辑器只允许单行文本。Company Public Info数据包括显示为简单文本字符串的url和电子邮件,以及理想情况下应该使用电话掩码格式的电话号码。最后,Private Company Info显示不应该立即可见的密码。
改变这种情况的一种方法是访问列对象并更新它们的设置,但这意味着每次将数据源绑定到数据感知控件时都应该这样做。另一种方法是使用Microsoft提供的、大多数DevExpress数据感知控件支持的数据注释属性。为了能够使用这些属性,请确保您的应用程序引用了System.ComponentModel.DataAnnotations名称空间。
有两种方法可以使用这些属性,第一种也是最简单的方法是在每个数据字段之前定义所需的属性,这就是对Product类所做的工作。某些属性指示数据类型,以便分配适当的单元格编辑器。ReadOnly属性允许您禁用特定字段的数据编辑,还可以应用数据输入验证规则,正如Range属性所做的那样。
C#
using System.ComponentModel.DataAnnotations; public class Product { [ReadOnly(true)] public double UnitPrice { get; set; } [EnumDataType(typeof(ProductCategory))] public int Category { get; set; } [Display(Description = "The amount of currently available product")] public int Quantity { get; set; } [DataType(DataType.Text), Display(Order = -1)] public string Text { get; set; } [DataType(DataType.MultilineText)] public string MultilineText { get; set; } [DataType(DataType.Currency), Range(200, 5000)] public int Currency { get; set; } [DataType(DataType.Date)] public DateTime Date { get; set; } [DataType(DataType.Time)] public DateTime Time { get; set; } }
VB.NET
Imports System.ComponentModel.DataAnnotations Public Class Product <[ReadOnly](True)> Public Property UnitPrice() As Double <EnumDataType(GetType(ProductCategory))> Public Property Category() As Integer <Display(Description := "The amount of currently available product")> Public Property Quantity() As Integer <DataType(DataType.Text), Display(Order := -1)> Public Property Text() As String <DataType(DataType.MultilineText)> Public Property MultilineText() As String <DataType(DataType.Currency), Range(200, 5000)> Public Property Currency() As Integer <DataType(DataType.Date)> Public Property [Date]() As Date <DataType(DataType.Time)> Public Property Time() As Date End Class
启动应用程序,切换到产品信息数据,看看它现在的样子。多行文本使用MemoEdit单元格编辑器,它允许我们完整地查看文本,而Currency列只允许指定范围内的数据。
当您拥有多个类中不使用的唯一数据字段时,这种方法非常有用,完成相同任务的另一种方法是使用MetadataType类属性。使用这种方法,您可以定义一次数据字段属性,然后将该定义用于多个类。它还可以提高代码的可读性,因为数据属性不必出现在每个属性定义之前。
Private 和 Public Company Info类都将使用由CompanyProductMetadata类定义的元数据。
C#
[MetadataType(typeof(CompanyProductMetadata))] public class CompanyPublicInfo { // ... } // ... public class CompanyProductMetadata { [Display(ShortName = "Company", Name = "Company Name", AutoGenerateFilter = false)] public object CompanyName; [Display(Order = 2)] public object Country; [Display(Order = 1), Editable(false)] public object City; [DataType(DataType.Url)] public object Url; [DataType(DataType.EmailAddress)] public object Email; [DataType(DataType.PhoneNumber), Required] public object Phone; [DataType(DataType.Text), Display(Order = -1)] public object Text; [Display(AutoGenerateField = false, Description = "This column isn't created")] public object AdditionalInfo; [DataType(DataType.Password), StringLength(20, MinimumLength = 3)] public object Password; // ... }
VB.NET
<MetadataType(GetType(CompanyProductMetadata))> Public Class CompanyPublicInfo ' ... End Class Public Class CompanyProductMetadata <Display(ShortName := "Company", Name := "Company Name", AutoGenerateFilter := False)> Public CompanyName As Object <Display(Order := 2)> Public Country As Object <Display(Order := 1), Editable(False)> Public City As Object <DataType(DataType.Url)> Public Url As Object <DataType(DataType.EmailAddress)> Public Email As Object <DataType(DataType.PhoneNumber), Required> Public Phone As Object <DataType(DataType.Text), Display(Order := -1)> Public Text As Object <Display(AutoGenerateField := False, Description := "This column isn't created")> Public AdditionalInfo As Object <DataType(DataType.Password), StringLength(20, MinimumLength := 3)> Public Password As Object ' ... End Class
运行应用程序来查看结果,切换到Public Company Info数据源,可以看到URL现在显示为实际的超链接,电话号码使用屏蔽输入。
完整代码
本例中的解决方案包括一个数据源文件,该文件有三个提供网格数据的类——CompanyPublicInfo、CompanyPrivateInfo和Product。它们三个的属性通过使用MetadataType属性从CompanyProductMetadata类派生数据注释属性。最终用户可以使用表单顶部的编辑器调用Get…方法之一,该方法将用示例数据填充网格。
重要提示:要使用数据注释属性,您需要在您的解决方案中引用System.ComponentModel.DataAnnotations库。
DataSource.cs
using System; using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text; using System.Threading.Tasks; namespace GridDataAttributes { [MetadataType(typeof(CompanyProductMetadata))] public class CompanyPublicInfo { public string CompanyName { get; set; } public string Country { get; set; } public string City { get; set; } public string Url { get; set; } public string Email { get; set; } public string Phone { get; set; } public string AdditionalInfo { get; set; } } [MetadataType(typeof(CompanyProductMetadata))] public class CompanyPrivateInfo { public string Password { get; set; } public DateTime Date2 { get; set; } public double Sales { get; set; } public double Profit { get; set; } public double SalesVsTarget { get; set; } public double MarketShare { get; set; } public double CustomersSatisfaction { get; set; } } public class Product { [ReadOnly(true)] public double UnitPrice { get; set; } [EnumDataType(typeof(ProductCategory))] public int Category { get; set; } [Display(Description = "The amount of currently available product")] public int Quantity { get; set; } [DataType(DataType.Text), Display(Order = -1)] public string Text { get; set; } [DataType(DataType.MultilineText)] public string MultilineText { get; set; } [DataType(DataType.Currency), Range(200, 5000)] public int Currency { get; set; } [DataType(DataType.Date)] public DateTime Date { get; set; } [DataType(DataType.Time)] public DateTime Time { get; set; } } public class CompanyProductMetadata { [Display(ShortName = "Company", Name = "Company Name", AutoGenerateFilter = false)] public object CompanyName; [Display(Order = 2)] public object Country; [Display(Order = 1), Editable(false)] public object City; [DataType(DataType.Url)] public object Url; [DataType(DataType.EmailAddress)] public object Email; [DataType(DataType.PhoneNumber), Required] public object Phone; [DataType(DataType.Text), Display(Order = -1)] public object Text; [Display(AutoGenerateField = false, Description = "This column isn't created")] public object AdditionalInfo; [DataType(DataType.Password), StringLength(20, MinimumLength = 3)] public object Password; [DisplayFormat(DataFormatString = "MMMM/yyyy"), Display(Name = "Date 2")] public object Date2; [DisplayFormat(DataFormatString = "#,##0,,M")] public object Sales; [DisplayFormat(DataFormatString = "#,##0,,M")] public object Profit; [DisplayFormat(DataFormatString = "p", ApplyFormatInEditMode = true), Display(Name = "Sales vs Target")] public object SalesVsTarget; [DisplayFormat(DataFormatString = "p0", ApplyFormatInEditMode = false)] public object MarketShare; [Display(Name = "Cust Satisfaction")] public object CustomersSatisfaction; } public enum ProductCategory { Beverages = 1, Fruit = 2, Vegetables = 3, Meat = 4, Condiments = 5, Confections = 6, DairyProducts = 7, GrainsCereals = 8, Seafood = 9 } public class GridSampleDataList { static public List<CompanyPrivateInfo> GetCompanyPrivateInfo() { return new List<CompanyPrivateInfo> { new CompanyPrivateInfo() { CustomersSatisfaction = 3.1, Date2 = DateTime.Now, MarketShare = 42, Password = "123qwerty", Profit = 4951515, Sales = 311414134, SalesVsTarget = 0.0277, } }; } static public List<CompanyPublicInfo> GetCompanyPublicInfo() { return new List<CompanyPublicInfo> { new CompanyPublicInfo() { AdditionalInfo = "Some Info", City = "Glendale", CompanyName = "Developer Express", Country = "USA", Email = "[email protected]", Phone = "1234567890", Url = "www.devexpress.com", } }; } static public List<Product> GetProductSample() { return new List<Product> { new Product() { Currency = 1000, Category = 2, Date = DateTime.Now, MultilineText = "Line1\r\nLine2\r\nLine3", Quantity = 321, Text = "Sample Text", Time = DateTime.Now, UnitPrice = 1800, } }; } } }
Form1.cs
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using DevExpress.XtraEditors; using DevExpress.XtraGrid.Views.Grid; namespace GridDataAttributes { public partial class Form1 : XtraForm { public Form1() { InitializeComponent(); gridView1.OptionsView.ShowGroupPanel = false; gridControl1.DataSourceChanged += gridControl1_DataSourceChanged; } void gridControl1_DataSourceChanged(object sender, EventArgs e) { gridControl1.MainView.PopulateColumns(); (gridControl1.MainView as GridView).BestFitColumns(); } protected override void onl oad(EventArgs e) { base.OnLoad(e); //gridControl1.DataSource = CompanyProductList.GetSampleData(); //companyProductListBindingSource.DataSource = CompanyProductList.GetSampleData(); //companyProductBindingSource.DataSource = CompanyProductList.GetSampleData(); } private void barEditItem3_EditValueChanged(object sender, EventArgs e) { switch (barEditItem3.EditValue as string) { case "Company public info": gridControl1.DataSource = GridSampleDataList.GetCompanyPublicInfo(); break; case "Company private info": gridControl1.DataSource = GridSampleDataList.GetCompanyPrivateInfo(); break; case "Product info": gridControl1.DataSource = GridSampleDataList.GetProductSample(); break; } } } }
Program.cs
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; using DevExpress.Skins; namespace GridDataAttributes { static class Program { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { SkinManager.EnableFormSkins(); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } } }
Program.vb
Imports System Imports System.Collections.Generic Imports System.Linq Imports System.Threading.Tasks Imports System.Windows.Forms Imports DevExpress.Skins Namespace GridDataAttributes Friend NotInheritable Class Program Private Sub New() End Sub ''' <summary> ''' The main entry point for the application. ''' </summary> <STAThread> _ Shared Sub Main() SkinManager.EnableFormSkins() Application.EnableVisualStyles() Application.SetCompatibleTextRenderingDefault(False) Application.Run(New Form1()) End Sub End Class End Namespace
Form1.vb
Imports System Imports System.Collections.Generic Imports System.ComponentModel Imports System.Data Imports System.Drawing Imports System.Linq Imports System.Text Imports System.Threading.Tasks Imports System.Windows.Forms Imports DevExpress.XtraEditors Imports DevExpress.XtraGrid.Views.Grid Namespace GridDataAttributes Partial Public Class Form1 Inherits XtraForm Public Sub New() InitializeComponent() gridView1.OptionsView.ShowGroupPanel = False AddHandler gridControl1.DataSourceChanged, AddressOf gridControl1_DataSourceChanged End Sub Private Sub gridControl1_DataSourceChanged(ByVal sender As Object, ByVal e As EventArgs) gridControl1.MainView.PopulateColumns() TryCast(gridControl1.MainView, GridView).BestFitColumns() End Sub Protected Overrides Sub onl oad(ByVal e As EventArgs) MyBase.OnLoad(e) 'gridControl1.DataSource = CompanyProductList.GetSampleData(); 'companyProductListBindingSource.DataSource = CompanyProductList.GetSampleData(); 'companyProductBindingSource.DataSource = CompanyProductList.GetSampleData(); End Sub Private Sub barEditItem3_EditValueChanged(ByVal sender As Object, ByVal e As EventArgs) Handles barEditItem3.EditValueChanged Select Case TryCast(barEditItem3.EditValue, String) Case "Company public info" gridControl1.DataSource = GridSampleDataList.GetCompanyPublicInfo() Case "Company private info" gridControl1.DataSource = GridSampleDataList.GetCompanyPrivateInfo() Case "Product info" gridControl1.DataSource = GridSampleDataList.GetProductSample() End Select End Sub End Class End Namespace
DataSource.vb
Imports System Imports System.Collections.Generic Imports System.ComponentModel Imports System.ComponentModel.DataAnnotations Imports System.Linq Imports System.Text Imports System.Threading.Tasks Namespace GridDataAttributes <MetadataType(GetType(CompanyProductMetadata))> _ Public Class CompanyPublicInfo Public Property CompanyName() As String Public Property Country() As String Public Property City() As String Public Property Url() As String Public Property Email() As String Public Property Phone() As String Public Property AdditionalInfo() As String End Class <MetadataType(GetType(CompanyProductMetadata))> _ Public Class CompanyPrivateInfo Public Property Password() As String Public Property Date2() As Date Public Property Sales() As Double Public Property Profit() As Double Public Property SalesVsTarget() As Double Public Property MarketShare() As Double Public Property CustomersSatisfaction() As Double End Class Public Class Product <[ReadOnly](True)> _ Public Property UnitPrice() As Double <EnumDataType(GetType(ProductCategory))> _ Public Property Category() As Integer <Display(Description := "The amount of currently available product")> _ Public Property Quantity() As Integer <DataType(DataType.Text), Display(Order := -1)> _ Public Property Text() As String <DataType(DataType.MultilineText)> _ Public Property MultilineText() As String <DataType(DataType.Currency), Range(200, 5000)> _ Public Property Currency() As Integer <DataType(DataType.Date)> _ Public Property [Date]() As Date <DataType(DataType.Time)> _ Public Property Time() As Date End Class Public Class CompanyProductMetadata <Display(ShortName := "Company", Name := "Company Name", AutoGenerateFilter := False)> _ Public CompanyName As Object <Display(Order := 2)> _ Public Country As Object <Display(Order := 1), Editable(False)> _ Public City As Object <DataType(DataType.Url)> _ Public Url As Object <DataType(DataType.EmailAddress)> _ Public Email As Object <DataType(DataType.PhoneNumber), Required> _ Public Phone As Object <DataType(DataType.Text), Display(Order := -1)> _ Public Text As Object <Display(AutoGenerateField := False, Description := "This column isn't created")> _ Public AdditionalInfo As Object <DataType(DataType.Password), StringLength(20, MinimumLength := 3)> _ Public Password As Object <DisplayFormat(DataFormatString := "MMMM/yyyy"), Display(Name := "Date 2")> _ Public Date2 As Object <DisplayFormat(DataFormatString := "#,##0,,M")> _ Public Sales As Object <DisplayFormat(DataFormatString := "#,##0,,M")> _ Public Profit As Object <DisplayFormat(DataFormatString := "p", ApplyFormatInEditMode := True), Display(Name := "Sales vs Target")> _ Public SalesVsTarget As Object <DisplayFormat(DataFormatString := "p0", ApplyFormatInEditMode := False)> _ Public MarketShare As Object <Display(Name := "Cust Satisfaction")> _ Public CustomersSatisfaction As Object End Class Public Enum ProductCategory Beverages = 1 Fruit = 2 Vegetables = 3 Meat = 4 Condiments = 5 Confections = 6 DairyProducts = 7 GrainsCereals = 8 Seafood = 9 End Enum Public Class GridSampleDataList Public Shared Function GetCompanyPrivateInfo() As List(Of CompanyPrivateInfo) Return New List(Of CompanyPrivateInfo) From { _ New CompanyPrivateInfo() With {.CustomersSatisfaction = 3.1, .Date2 = Date.Now, .MarketShare = 42, .Password = "123qwerty", .Profit = 4951515, .Sales = 311414134, .SalesVsTarget = 0.0277} _ } End Function Public Shared Function GetCompanyPublicInfo() As List(Of CompanyPublicInfo) Return New List(Of CompanyPublicInfo) From { _ New CompanyPublicInfo() With {.AdditionalInfo = "Some Info", .City = "Glendale", .CompanyName = "Developer Express", .Country = "USA", .Email = "[email protected]", .Phone = "1234567890", .Url = "www.devexpress.com"} _ } End Function Public Shared Function GetProductSample() As List(Of Product) Return New List(Of Product) From { _ New Product() With {.Currency = 1000, .Category = 2, .Date = Date.Now, .MultilineText = "Line1" & ControlChars.CrLf & "Line2" & ControlChars.CrLf & "Line3", .Quantity = 321, .Text = "Sample Text", .Time = Date.Now, .UnitPrice = 1800} _ } End Function End Class End Namespace标签:End,get,DevExpress,System,Public,WinForms,Grid,Property,public From: https://www.cnblogs.com/AABBbaby/p/18554250