76、数据控件:验证、表单与网格的综合指南

数据控件:验证、表单与网格的综合指南

在数据处理和展示的领域中,有许多强大的工具和技术可以帮助我们创建出功能丰富、易于使用的应用程序。本文将深入探讨一些重要的数据控件,包括验证摘要、数据字段表单、数据注解以及数据网格,为你提供全面的技术指南。

1. 验证摘要(ValidationSummary)

验证摘要控件提供了多个属性,可用于自定义其外观。以下是一些常用属性及其用途:
- HeaderTemplate :用于提供一个数据模板,改变标题的呈现方式。
- Header :用于提供自定义的标题文本。
- SummaryListBoxStyle :用于更改错误列表的格式。

在编程方面,你可以检查 HasErrors 属性来确定表单是否有效,并通过 Errors 集合检查检测到的所有问题。

2. 数据字段表单(DataField 和 DataForm)

如果你使用 Silverlight 工具包,有两个工具可帮助你构建丰富的数据表单。

2.1 数据字段控件(DataField)

这是一个一体化的控件,用于编辑单个绑定属性。它结合了标签控件(Label)、描述查看器控件(DescriptionViewer)和输入控件(如文本框)。

2.2 数据表单控件(DataForm)

这是一个更强大的工具,是一个单一容器,可创建显示和编辑数据对象所需的所有绑定控件。使用方法如下:
- 显示单个数据对象时,设置 CurrentItem 属性:

dataForm.CurrentItem = product
  • 显示多个数据对象时,设置 ItemsSource 属性:
dataForm.ItemsSource = products

无论哪种方式,数据表单都会为数据对象的每个属性创建输入控件,并为每个属性配备标签和描述查看器。如果使用 ItemsSource 属性绑定多个项目,数据表单还会在表单顶部添加一个带有导航控件的栏,用户可以通过这些控件浏览记录、添加新记录和删除现有记录。

数据表单包含许多用于调整其外观的属性和可自定义的模板,但为了实现完全的可定制性,大多数开发人员仍会手动创建数据表单标记。

3. 数据注解(Data Annotations)

数据注解是一种强大的功能,可帮助你更轻松地实现数据验证规则。在 Silverlight 中,当前的验证机制是对设置属性时发生的未处理异常做出响应。如果要实现自定义验证,需要在属性设置器中编写代码来测试新值,并在必要时抛出异常,这种方式编写和维护验证代码都很繁琐。

数据注解允许你通过将一个或多个属性附加到数据类的属性上来应用验证规则。正确使用数据注解可以将数据验证从代码中分离出来,放入声明性元数据中,从而提高代码的清晰度和类的可维护性。

3.1 引发注解错误

在使用数据注解之前,需要添加对 System.ComponentModel.DataAnnotations.dll 程序集的引用。所有数据注解类都位于 System.ComponentModel.DataAnnotations 命名空间中。

以下是一个使用 StringLength 属性限制 ModelName 字段最大长度为 25 个字符的示例:

<StringLength(25)>, _
<Display(Name := "Model Name", Description := "This is the retail product name.")> _
Public Property ModelName() As String
    Get
        Return modelName
    End Get
    Set(ByVal value As String)
        modelName = value
        OnPropertyChanged(New PropertyChangedEventArgs("ModelName"))
    End Set
End Property

虽然上述设置看起来很完美,但 Silverlight 的数据绑定系统还需要抛出异常才能识别无效数据。可以使用 Validator 类的共享辅助方法来测试数据注解并检查属性是否存在错误数据。例如,使用 ValidateProperty() 方法检查属性值:

<StringLength(25)>, _
<Display(Name := "Model Name", Description := "This is the retail product name.")> _
Public Property ModelName() As String
    Get
        Return modelName
    End Get
    Set(ByVal value As String)
        ' Explicitly raise an exception if a data annotation attribute
        ' fails validation.
        Dim context As New ValidationContext(Me, Nothing, Nothing)
        context.MemberName = "ModelName"
        Validator.ValidateProperty(value, context)

        modelName = value
        OnPropertyChanged(New PropertyChangedEventArgs("ModelName"))
    End Set
End Property

需要注意的是,数据注解并非适用于所有场景,它仍要求数据类抛出异常来指示错误条件,这种设计模式在某些情况下可能不合适。

4. 注解属性

要使用数据注解进行验证,需要向数据类添加正确的属性。以下是一些常用的注解属性:

属性 描述 示例
Required 指定字段必须存在,如果为空,用户将收到错误信息。 <Required()> _ Public Property ModelNumber() As String
StringLength 设置字符串的最大长度,还可(可选)设置最小长度。 <StringLength(25, MinimumLength := 5)> _ Public Property ModelName() As String
Range 强制值落在最小值和最大值之间的范围内。 <Range(0,1000)> _ Public Property UnitsInStock() As Integer
RegularExpression 使用正则表达式测试文本值。 <RegularExpression("^[A-Za-z0-9]+$")> _ Public Property ModelNumber() As String
CustomValidation 允许在单独的类中编写自定义验证逻辑,并将其附加到单个属性或整个数据对象。 见后续示例
4.1 正则表达式基础

正则表达式由字面字符和元字符组成。字面字符代表特定的定义字符,元字符是通配符,可以代表一系列值。以下是一些常见的元字符及其规则:

字符 规则 示例
* 表示前一个字符或子表达式的零个或多个匹配。 a*b 匹配 aab b
+ 表示前一个字符或子表达式的一个或多个匹配。 a+b 匹配 aab 但不匹配 a
( ) 用于分组子表达式,将其视为一个单独的元素。 (ab)+ 匹配 ab ababab
{m} 要求前一个字符或组重复 m 次。 a{3} 匹配 aaa
{m, n} 要求前一个字符或组重复 n 到 m 次。 a{2,3} 匹配 aa aaa 但不匹配 aaaa
\| 表示两个匹配中的任意一个。 a\|b 匹配 a b
[ ] 匹配一个有效字符范围内的单个字符。 [A-C] 匹配 A B C
[^ ] 匹配不在给定范围内的字符。 [^A-C] 匹配除 A B C 之外的任何字符
. 表示除换行符之外的任何字符。
\s 表示任何空白字符(如制表符或空格)。
\S 表示任何非空白字符。
\d 表示任何数字字符。
\D 表示任何非数字字符。
\w 表示任何字母数字字符(字母、数字或下划线)。
^ 表示字符串的开始。 ^ab 仅当字符串以 ab 开头时才能匹配
$ 表示字符串的结束。 ab$ 仅当字符串以 ab 结尾时才能匹配
\ 表示后续字符是字面字符。 \\ 表示字面的 \ \+ 表示字面的 +

正则表达式非常强大,但在很多情况下,你不需要自己编写,而是可以在网上找到现成的用于验证邮政编码、电子邮件地址等的表达式。

4.2 自定义验证(CustomValidation)

自定义验证属性允许你在单独的类中编写自己的验证逻辑,并将其附加到单个属性或整个数据对象。以下是一个自定义验证类的示例:

Public Class ProductValidation
    Public Shared Function ValidateUnitCost(ByVal value As Double, _
      ByVal context As ValidationContext) As ValidationResult
        ' Get the cents portion.
        Dim valueString As String = value.ToString()
        Dim cents As String = ""
        Dim decimalPosition As Integer = valueString.IndexOf(".")
        If decimalPosition <> -1 Then
            cents = valueString.Substring(decimalPosition)
        End If

        ' Perform the validation test.     
        If (cents <> ".75") AndAlso (cents <> ".99") AndAlso (cents <> ".95") Then
            Return New ValidationResult( _
              "Retail prices must end with .75, .95, or .99 to be valid.")
        Else
            Return ValidationResult.Success
        End If
    End Function
End Class

要将此验证逻辑附加到属性上,可以使用 CustomValidation 属性:

<CustomValidation(GetType(ProductValidation), "ValidateUnitCost")> _
Public Property UnitCost() As Double
    ...
End Property

你还可以使用 CustomValidation 属性附加类级别的验证规则。例如,检查 ModelNumber ModelName 属性是否具有不同的值:

Public Shared Function ValidateProduct(ByVal product As Product, _
  ByVal context As ValidationContext) As ValidationResult
    If product.ModelName = product.ModelNumber Then
        Return New ValidationResult( _
          "You can't use the same model number as the model name.")
    Else
        Return ValidationResult.Success
    End If
End Function

并将其附加到 Product 类上:

<CustomValidation(GetType(ProductValidation), "ValidateProduct")> _
Public Class Product
    Implements INotifyPropertyChanged
    ...
End Class

不过,类级别的验证规则有一个明显的缺点,需要你调用 Validator.ValidateObject() 方法来强制执行。在某些情况下,可能不太方便。

5. 数据网格(DataGrid)

数据网格是一个数据显示控件,它从对象集合中获取信息,并将其呈现为行和单元格的网格。每行对应一个单独的对象,每列对应该对象的一个属性。

数据网格具有以下优点:
- 灵活性 :使用基于列的模型,可精确定义要使用的列,并提供绑定表达式以从绑定对象中提取数据。还支持模板和值转换器等重要工具。
- 可定制性 :可以使用属性、标题和样式彻底改变数据网格的外观,甚至可以为整个数据网格提供新的控件模板。
- 编辑功能 :可以监控编辑过程并回滚无效更改,支持基于异常的验证和数据注解。
- 性能 :使用虚拟化技术,仅保留当前可见数据的内存对象,大大减少了内存开销,能够处理大量数据而不会严重减慢速度。

5.1 创建简单网格

数据网格定义在 System.Windows.Controls 命名空间中,但部署在不同的程序集 System.Windows.Controls.Data.dll 中。默认情况下,Silverlight 项目没有对此程序集的引用,但当你从工具箱添加数据网格时,Visual Studio 会自动添加引用并插入新的命名空间映射:

<UserControl xmlns:data= 
 "clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" ... 
>

要创建一个简单的数据网格,可以使用自动列生成功能。设置 AutoGenerateColumns 属性为 True (默认值):

<data:DataGrid x:Name="gridProducts" AutoGenerateColumns="True">
</data:DataGrid>

然后,通过设置 ItemsSource 属性填充数据网格:

gridProducts.DataSource = products

使用自动列生成时,数据网格会使用反射查找绑定数据对象的每个公共属性,并为每个属性创建一列。对于非字符串属性,数据网格会调用 ToString() 方法进行显示。

5.2 自定义数据网格的基本显示

以下是一些可用于自定义数据网格基本显示的属性:

成员 描述
RowBackground AlternatingRowBackground RowBackground 设置每行后面的背景画笔。如果设置了 AlternatingRowBackground ,则交替行将使用不同的背景颜色绘制,便于区分行。默认情况下,奇数行背景为白色,偶数行背景为浅灰色。
ColumnHeaderHeight 数据网格顶部列标题行的高度(以像素为单位)。
RowHeaderWidth 行标题列的宽度(以像素为单位)。此列位于网格最左侧,不显示数据,但用于指示当前选中的行和正在编辑的行。
ColumnWidth 每列的默认宽度。如果显式定义列,可以覆盖此宽度以调整单个列的大小。默认列宽为 100 像素。
RowHeight 每行的高度。如果计划在数据网格中显示多行文本或不同内容(如图像),此设置很有用。用户无法调整行高。
GridlinesVisibility 来自 DataGridGridlines 枚举的值,用于确定显示哪些网格线(水平、垂直、无或全部)。
VerticalGridlinesBrush 用于绘制列之间网格线的画笔。
HorizontalGridlinesBrush 用于绘制行之间网格线的画笔。
HeadersVisibility 来自 DataGridHeaders 枚举的值,用于确定显示哪些标题(列、行、全部或无)。
HorizontalScrollBarVisibility VerticalScrollBarVisibility 来自 ScrollBarVisibility 枚举的值,用于确定何时显示滚动条(需要时自动显示、始终显示或从不显示)。默认值为 Auto 。如果包含一个或多个星号大小的列,则不会显示水平滚动条。

通过合理使用这些属性和功能,你可以创建出功能强大、外观精美的数据展示和编辑界面。希望本文能为你在数据控件的使用上提供有价值的参考。

数据控件:验证、表单与网格的综合指南

6. 数据网格的高级应用与操作流程

在实际应用中,数据网格的使用往往需要更细致的操作和配置。下面将详细介绍数据网格在不同场景下的高级应用以及具体的操作流程。

6.1 手动定义列

当自动列生成无法满足需求时,你可以手动定义列。手动定义列可以让你更精确地控制数据的显示和绑定。以下是一个手动定义列的示例:

<data:DataGrid x:Name="gridProducts">
    <data:DataGrid.Columns>
        <data:DataGridTextColumn Header="Model Name" Binding="{Binding ModelName}" />
        <data:DataGridTextColumn Header="Model Number" Binding="{Binding ModelNumber}" />
        <data:DataGridTextColumn Header="Units in Stock" Binding="{Binding UnitsInStock}" />
    </data:DataGrid.Columns>
</data:DataGrid>

在这个示例中,我们手动定义了三列,分别绑定到数据对象的 ModelName ModelNumber UnitsInStock 属性。通过这种方式,你可以根据需要选择要显示的属性,并且可以对每列进行个性化的设置。

6.2 数据网格的排序功能

数据网格支持排序功能,用户可以通过点击列标题对数据进行排序。要启用排序功能,只需将列的 CanUserSort 属性设置为 True (默认值为 True )。以下是一个启用排序功能的示例:

<data:DataGrid x:Name="gridProducts">
    <data:DataGrid.Columns>
        <data:DataGridTextColumn Header="Model Name" Binding="{Binding ModelName}" CanUserSort="True" />
        <data:DataGridTextColumn Header="Model Number" Binding="{Binding ModelNumber}" CanUserSort="True" />
        <data:DataGridTextColumn Header="Units in Stock" Binding="{Binding UnitsInStock}" CanUserSort="True" />
    </data:DataGrid.Columns>
</data:DataGrid>

用户点击列标题时,数据网格会自动对该列的数据进行升序或降序排序。

6.3 数据网格的选择功能

数据网格支持多种选择模式,包括单选和多选。你可以通过设置 SelectionMode 属性来指定选择模式。以下是不同选择模式的示例:
- 单选模式

<data:DataGrid x:Name="gridProducts" SelectionMode="Single">
    ...
</data:DataGrid>

在单选模式下,用户只能选择一行数据。
- 多选模式

<data:DataGrid x:Name="gridProducts" SelectionMode="Extended">
    ...
</data:DataGrid>

在多选模式下,用户可以通过按住 Ctrl Shift 键来选择多行数据。

6.4 数据网格的操作流程

下面是一个使用数据网格的基本操作流程:
1. 添加引用 :确保项目中引用了 System.Windows.Controls.Data.dll 程序集。
2. 定义数据网格 :在 XAML 中定义数据网格,可以选择自动列生成或手动定义列。
3. 绑定数据 :在代码中设置数据网格的 ItemsSource 属性,将其绑定到数据集合。
4. 配置功能 :根据需要配置排序、选择等功能。
5. 处理事件 :可以处理数据网格的各种事件,如 SelectionChanged 事件,以实现特定的业务逻辑。

以下是一个完整的示例代码,展示了如何实现上述操作流程:

<UserControl xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" ...>
    <data:DataGrid x:Name="gridProducts" SelectionMode="Extended">
        <data:DataGrid.Columns>
            <data:DataGridTextColumn Header="Model Name" Binding="{Binding ModelName}" CanUserSort="True" />
            <data:DataGridTextColumn Header="Model Number" Binding="{Binding ModelNumber}" CanUserSort="True" />
            <data:DataGridTextColumn Header="Units in Stock" Binding="{Binding UnitsInStock}" CanUserSort="True" />
        </data:DataGrid.Columns>
    </data:DataGrid>
</UserControl>
Public Class MainPage
    Public Sub New()
        InitializeComponent()

        ' 假设 products 是一个数据集合
        Dim products As New List(Of Product)()
        ' 填充数据集合
        ' ...

        gridProducts.ItemsSource = products
    End Sub
End Class
7. 数据验证与数据网格的结合

数据验证是确保数据准确性和完整性的重要手段。在数据网格中,我们可以结合数据注解和异常处理来实现数据验证。

7.1 数据注解在数据网格中的应用

当使用数据注解时,数据网格会自动识别并处理验证错误。例如,如果你在数据类的属性上应用了 Required 注解,当用户尝试删除该字段的值时,数据网格会显示错误提示。以下是一个使用数据注解的示例:

<Required(ErrorMessage := "Model Number is required.")> _
Public Property ModelNumber() As String
    Get
        Return modelNumber
    End Get
    Set(ByVal value As String)
        modelNumber = value
        OnPropertyChanged(New PropertyChangedEventArgs("ModelNumber"))
    End Set
End Property

在数据网格中,当用户删除 ModelNumber 字段的值时,会显示错误提示信息。

7.2 异常处理在数据网格中的应用

除了数据注解,数据网格还支持基于异常的验证。当在属性设置器中抛出异常时,数据网格会捕获该异常并显示错误提示。以下是一个基于异常的验证示例:

Public Property UnitsInStock() As Integer
    Get
        Return unitsInStock
    End Get
    Set(ByVal value As Integer)
        If value < 0 Then
            Throw New ArgumentException("Units in stock cannot be negative.")
        End If
        unitsInStock = value
        OnPropertyChanged(New PropertyChangedEventArgs("UnitsInStock"))
    End Set
End Property

在这个示例中,如果用户输入的 UnitsInStock 值为负数,会抛出异常,数据网格会显示相应的错误提示。

8. 数据表单与数据网格的协同工作

在实际应用中,数据表单和数据网格通常会协同工作。用户可以在数据网格中选择一条记录,然后在数据表单中对该记录进行编辑。以下是一个实现数据表单与数据网格协同工作的示例:

<StackPanel>
    <data:DataGrid x:Name="gridProducts" SelectionChanged="gridProducts_SelectionChanged">
        <data:DataGrid.Columns>
            <data:DataGridTextColumn Header="Model Name" Binding="{Binding ModelName}" />
            <data:DataGridTextColumn Header="Model Number" Binding="{Binding ModelNumber}" />
            <data:DataGridTextColumn Header="Units in Stock" Binding="{Binding UnitsInStock}" />
        </data:DataGrid.Columns>
    </data:DataGrid>
    <data:DataForm x:Name="dataFormProduct" CurrentItem="{Binding SelectedItem, ElementName=gridProducts}" />
</StackPanel>
Public Class MainPage
    Public Sub New()
        InitializeComponent()

        ' 假设 products 是一个数据集合
        Dim products As New List(Of Product)()
        ' 填充数据集合
        ' ...

        gridProducts.ItemsSource = products
    End Sub

    Private Sub gridProducts_SelectionChanged(sender As Object, e As SelectionChangedEventArgs)
        ' 当数据网格的选择发生变化时,更新数据表单的当前项
        dataFormProduct.CurrentItem = gridProducts.SelectedItem
    End Sub
End Class

在这个示例中,当用户在数据网格中选择一条记录时,数据表单会自动显示该记录的详细信息,用户可以在数据表单中对该记录进行编辑。

9. 总结与展望

通过本文的介绍,我们了解了数据控件中的验证摘要、数据字段表单、数据注解、数据网格等重要组件的使用方法和技巧。这些组件可以帮助我们创建功能丰富、易于使用的数据展示和编辑界面。

在实际应用中,我们可以根据具体需求选择合适的组件和方法。例如,对于简单的数据展示和编辑,可以使用自动列生成的方式创建数据网格;对于复杂的数据验证,可以使用数据注解和自定义验证来确保数据的准确性和完整性。

未来,随着技术的不断发展,数据控件可能会提供更多的功能和更好的性能。例如,可能会支持更复杂的模板和样式,以及更高效的数据处理和验证机制。我们可以期待这些技术的发展,为我们的开发工作带来更多的便利和可能性。

总之,掌握这些数据控件的使用方法,将有助于我们提高开发效率,创建出高质量的数据应用程序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值