Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
A DataGrid vezérlőelem lehetővé teszi az érvényesítést mind a cella, mind a sor szintjén. A cellaszintű ellenőrzéssel egy kötött adatobjektum egyedi tulajdonságait érvényesítheti, amikor egy felhasználó frissít egy értéket. A sorszintű ellenőrzéssel teljes adatobjektumokat érvényesíthet, amikor egy felhasználó véglegesíti a sor módosításait. Testre szabott vizuális visszajelzést is adhat az érvényesítési hibákhoz, vagy használhatja a DataGrid vezérlő által biztosított alapértelmezett vizuális visszajelzést.
Az alábbi eljárások bemutatják, hogyan alkalmazhatók érvényesítési szabályok DataGrid kötésekre, és hogyan szabhatók testre a vizuális visszajelzések.
Az egyes cellaértékek ellenőrzése
Adjon meg egy vagy több érvényesítési szabályt az oszlophoz használt kötésen. Ez hasonló az adatok egyszerű vezérlőkben való érvényesítéséhez, a Adatkötés áttekintésecímű cikkben leírtak szerint.
Az alábbi példa egy DataGrid vezérlőelemet mutat be, amelynek négy oszlopa egy üzleti objektum különböző tulajdonságaihoz van kötve. Három oszlop adja meg a ExceptionValidationRule úgy, hogy a ValidatesOnExceptions tulajdonságot
trueértékre állítja.<Grid> <Grid.Resources> <local:Courses x:Key="courses"/> </Grid.Resources> <DataGrid Name="dataGrid1" FontSize="20" ItemsSource="{StaticResource courses}" AutoGenerateColumns="False"> <DataGrid.Columns> <DataGridTextColumn Header="Course Name" Binding="{Binding Name, TargetNullValue=(enter a course name)}"/> <DataGridTextColumn Header="Course ID" Binding="{Binding Id, ValidatesOnExceptions=True}"/> <DataGridTextColumn Header="Start Date" Binding="{Binding StartDate, ValidatesOnExceptions=True, StringFormat=d}"/> <DataGridTextColumn Header="End Date" Binding="{Binding EndDate, ValidatesOnExceptions=True, StringFormat=d}"/> </DataGrid.Columns> </DataGrid> </Grid>Ha egy felhasználó érvénytelen értéket ad meg (például egy nem egész számot a Tanfolyamazonosító oszlopban), piros szegély jelenik meg a cella körül. Ezt az alapértelmezett érvényesítési visszajelzést az alábbi eljárásban leírtak szerint módosíthatja.
A cellaérvényesítési visszajelzés testreszabása
Állítsa az oszlop EditingElementStyle tulajdonságát az oszlop szerkesztési vezérlőjének megfelelő stílusra. Mivel a szerkesztési vezérlők futásidőben jönnek létre, a Validation.ErrorTemplate csatolt tulajdonságot nem tudja úgy használni, mint az egyszerű vezérlők esetében.
Az alábbi példa úgy frissíti az előző példát, hogy hozzáad egy, a három oszlop által megosztott hibastílust érvényesítési szabályokkal. Ha egy felhasználó érvénytelen értéket ad meg, a stílus megváltoztatja a cella háttérszínét, és hozzáad egy elemleírást. Figyelje meg az eseményindító használatát annak megállapításához, hogy van-e érvényesítési hiba. Erre azért van szükség, mert jelenleg nincs dedikált hibasablon a cellákhoz.
<DataGrid.Resources> <Style x:Key="errorStyle" TargetType="{x:Type TextBox}"> <Setter Property="Padding" Value="-2"/> <Style.Triggers> <Trigger Property="Validation.HasError" Value="True"> <Setter Property="Background" Value="Red"/> <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}"/> </Trigger> </Style.Triggers> </Style> </DataGrid.Resources> <DataGrid.Columns> <DataGridTextColumn Header="Course Name" Binding="{Binding Name, TargetNullValue=(enter a course name)}"/> <DataGridTextColumn Header="Course ID" EditingElementStyle="{StaticResource errorStyle}" Binding="{Binding Id, ValidatesOnExceptions=True}"/> <DataGridTextColumn Header="Start Date" EditingElementStyle="{StaticResource errorStyle}" Binding="{Binding StartDate, ValidatesOnExceptions=True, StringFormat=d}"/> <DataGridTextColumn Header="End Date" EditingElementStyle="{StaticResource errorStyle}" Binding="{Binding EndDate, ValidatesOnExceptions=True, StringFormat=d}"/> </DataGrid.Columns>Az oszlop által használt CellStyle lecserélésével szélesebb körű testreszabást valósíthat meg.
Több érték ellenőrzése egyetlen sorban
Implementáljon egy ValidationRule alosztályt, amely a kötött adatobjektum több tulajdonságát ellenőrzi. A Validate metódus implementálásában adja át a
valueparaméter értékét egy BindingGroup-példányra. Ezután az adatobjektumot a Items tulajdonságon keresztül érheti el.Az alábbi példa ezt a folyamatot mutatja be annak ellenőrzésére, hogy egy
StartDateobjektumCoursetulajdonságértéke korábbi-e aEndDatetulajdonságértékénél.public class CourseValidationRule : ValidationRule { public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo) { Course course = (value as BindingGroup).Items[0] as Course; if (course.StartDate > course.EndDate) { return new ValidationResult(false, "Start Date must be earlier than End Date."); } else { return ValidationResult.ValidResult; } } }Public Class CourseValidationRule Inherits ValidationRule Public Overrides Function Validate(ByVal value As Object, _ ByVal cultureInfo As System.Globalization.CultureInfo) _ As ValidationResult Dim course As Course = _ CType(CType(value, BindingGroup).Items(0), Course) If course.StartDate > course.EndDate Then Return New ValidationResult(False, _ "Start Date must be earlier than End Date.") Else Return ValidationResult.ValidResult End If End Function End ClassAdja hozzá az érvényesítési szabályt a DataGrid.RowValidationRules gyűjteményhez. A RowValidationRules tulajdonság közvetlen hozzáférést biztosít egy ValidationRules példány BindingGroup tulajdonságához, amely a vezérlőelem által használt összes kötést csoportosítja.
Az alábbi példa az XAML RowValidationRules tulajdonságát állítja be. A ValidationStep tulajdonság UpdatedValue van beállítva, így az ellenőrzés csak a kötött adatobjektum frissítése után történik.
<DataGrid.RowValidationRules> <local:CourseValidationRule ValidationStep="UpdatedValue"/> </DataGrid.RowValidationRules>Ha egy felhasználó a kezdő dátumnál korábbi záródátumot ad meg, a sorfejlécben piros felkiáltójel (!) jelenik meg. Ezt az alapértelmezett érvényesítési visszajelzést az alábbi eljárásban leírtak szerint módosíthatja.
Sorérvényesítési visszajelzés testreszabása
Állítsa be a DataGrid.RowValidationErrorTemplate tulajdonságot. Ez a tulajdonság lehetővé teszi a sorérvényesítési visszajelzések testreszabását az egyes DataGrid vezérlőkhöz. Több vezérlőt is érinthet, ha implicit sorstílust használ a DataGridRow.ValidationErrorTemplate tulajdonság beállításához.
Az alábbi példa az alapértelmezett sorérvényesítési visszajelzést egy láthatóbb mutatóra cseréli. Ha egy felhasználó érvénytelen értéket ad meg, megjelenik egy piros kör fehér felkiáltójellel a sorfejlécben. Ez sor- és cellaérvényesítési hibák esetén is előfordul. A társított hibaüzenet egy súgóablakban jelenik meg.
<DataGrid.RowValidationErrorTemplate> <ControlTemplate> <Grid Margin="0,-2,0,-2" ToolTip="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridRow}}, Path=(Validation.Errors)[0].ErrorContent}"> <Ellipse StrokeThickness="0" Fill="Red" Width="{TemplateBinding FontSize}" Height="{TemplateBinding FontSize}" /> <TextBlock Text="!" FontSize="{TemplateBinding FontSize}" FontWeight="Bold" Foreground="White" HorizontalAlignment="Center" /> </Grid> </ControlTemplate> </DataGrid.RowValidationErrorTemplate>
példa
Az alábbi példa teljes bemutatót nyújt a cella- és sorérvényesítéshez. A Course osztály egy mintaadat-objektumot biztosít, amely IEditableObject valósít meg a tranzakciók támogatásához. A DataGrid vezérlő IEditableObject kommunikál, hogy a felhasználók az ESC lenyomásával visszaállíthassák a módosításokat.
Megjegyzés:
Ha Visual Basicet használ, a MainWindow.xaml első sorában cserélje le a x:Class="DataGridValidation.MainWindow"x:Class="MainWindow".
Az ellenőrzés teszteléséhez próbálkozzon az alábbiakval:
A Tanfolyamazonosító oszlopban adjon meg egy nem egész számot.
A Záró dátum oszlopban adjon meg egy, a kezdő dátumnál korábbi dátumot.
Törölje az értéket a tanfolyamazonosítóban, a kezdő dátumban vagy a záródátumban.
Érvénytelen cellaérték visszavonásához helyezze vissza a kurzort a cellába, és nyomja le az ESC billentyűt.
Ha egy teljes sor módosításait vissza szeretné vonni, amikor az aktuális cella szerkesztési módban van, nyomja le kétszer az ESC billentyűt.
Érvényesítési hiba esetén vigye az egérmutatót a sorfejléc mutatója fölé a kapcsolódó hibaüzenet megtekintéséhez.
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace DataGridValidation
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
dataGrid1.InitializingNewItem += (sender, e) =>
{
Course newCourse = e.NewItem as Course;
newCourse.StartDate = newCourse.EndDate = DateTime.Today;
};
}
}
public class Courses : ObservableCollection<Course>
{
public Courses()
{
this.Add(new Course
{
Name = "Learning WPF",
Id = 1001,
StartDate = new DateTime(2010, 1, 11),
EndDate = new DateTime(2010, 1, 22)
});
this.Add(new Course
{
Name = "Learning Silverlight",
Id = 1002,
StartDate = new DateTime(2010, 1, 25),
EndDate = new DateTime(2010, 2, 5)
});
this.Add(new Course
{
Name = "Learning Expression Blend",
Id = 1003,
StartDate = new DateTime(2010, 2, 8),
EndDate = new DateTime(2010, 2, 19)
});
this.Add(new Course
{
Name = "Learning LINQ",
Id = 1004,
StartDate = new DateTime(2010, 2, 22),
EndDate = new DateTime(2010, 3, 5)
});
}
}
public class Course : IEditableObject, INotifyPropertyChanged
{
private string _name;
public string Name
{
get
{
return _name;
}
set
{
if (_name == value) return;
_name = value;
OnPropertyChanged("Name");
}
}
private int _number;
public int Id
{
get
{
return _number;
}
set
{
if (_number == value) return;
_number = value;
OnPropertyChanged("Id");
}
}
private DateTime _startDate;
public DateTime StartDate
{
get
{
return _startDate;
}
set
{
if (_startDate == value) return;
_startDate = value;
OnPropertyChanged("StartDate");
}
}
private DateTime _endDate;
public DateTime EndDate
{
get
{
return _endDate;
}
set
{
if (_endDate == value) return;
_endDate = value;
OnPropertyChanged("EndDate");
}
}
#region IEditableObject
private Course backupCopy;
private bool inEdit;
public void BeginEdit()
{
if (inEdit) return;
inEdit = true;
backupCopy = this.MemberwiseClone() as Course;
}
public void CancelEdit()
{
if (!inEdit) return;
inEdit = false;
this.Name = backupCopy.Name;
this.Id = backupCopy.Id;
this.StartDate = backupCopy.StartDate;
this.EndDate = backupCopy.EndDate;
}
public void EndEdit()
{
if (!inEdit) return;
inEdit = false;
backupCopy = null;
}
#endregion
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
public class CourseValidationRule : ValidationRule
{
public override ValidationResult Validate(object value,
System.Globalization.CultureInfo cultureInfo)
{
Course course = (value as BindingGroup).Items[0] as Course;
if (course.StartDate > course.EndDate)
{
return new ValidationResult(false,
"Start Date must be earlier than End Date.");
}
else
{
return ValidationResult.ValidResult;
}
}
}
}
Imports System.Collections.ObjectModel
Imports System.ComponentModel
Public Class MainWindow
Private Sub dataGrid1_InitializingNewItem(ByVal sender As System.Object, _
ByVal e As System.Windows.Controls.InitializingNewItemEventArgs) _
Handles dataGrid1.InitializingNewItem
Dim newCourse As Course = CType(e.NewItem, Course)
newCourse.StartDate = DateTime.Today
newCourse.EndDate = DateTime.Today
End Sub
End Class
Public Class Courses
Inherits ObservableCollection(Of Course)
Sub New()
Me.Add(New Course With { _
.Name = "Learning WPF", _
.Id = 1001, _
.StartDate = New DateTime(2010, 1, 11), _
.EndDate = New DateTime(2010, 1, 22) _
})
Me.Add(New Course With { _
.Name = "Learning Silverlight", _
.Id = 1002, _
.StartDate = New DateTime(2010, 1, 25), _
.EndDate = New DateTime(2010, 2, 5) _
})
Me.Add(New Course With { _
.Name = "Learning Expression Blend", _
.Id = 1003, _
.StartDate = New DateTime(2010, 2, 8), _
.EndDate = New DateTime(2010, 2, 19) _
})
Me.Add(New Course With { _
.Name = "Learning LINQ", _
.Id = 1004, _
.StartDate = New DateTime(2010, 2, 22), _
.EndDate = New DateTime(2010, 3, 5) _
})
End Sub
End Class
Public Class Course
Implements IEditableObject, INotifyPropertyChanged
Private _name As String
Public Property Name As String
Get
Return _name
End Get
Set(ByVal value As String)
If _name = value Then Return
_name = value
OnPropertyChanged("Name")
End Set
End Property
Private _number As Integer
Public Property Id As Integer
Get
Return _number
End Get
Set(ByVal value As Integer)
If _number = value Then Return
_number = value
OnPropertyChanged("Id")
End Set
End Property
Private _startDate As DateTime
Public Property StartDate As DateTime
Get
Return _startDate
End Get
Set(ByVal value As DateTime)
If _startDate = value Then Return
_startDate = value
OnPropertyChanged("StartDate")
End Set
End Property
Private _endDate As DateTime
Public Property EndDate As DateTime
Get
Return _endDate
End Get
Set(ByVal value As DateTime)
If _endDate = value Then Return
_endDate = value
OnPropertyChanged("EndDate")
End Set
End Property
#Region "IEditableObject"
Private backupCopy As Course
Private inEdit As Boolean
Public Sub BeginEdit() Implements IEditableObject.BeginEdit
If inEdit Then Return
inEdit = True
backupCopy = CType(Me.MemberwiseClone(), Course)
End Sub
Public Sub CancelEdit() Implements IEditableObject.CancelEdit
If Not inEdit Then Return
inEdit = False
Me.Name = backupCopy.Name
Me.Id = backupCopy.Id
Me.StartDate = backupCopy.StartDate
Me.EndDate = backupCopy.EndDate
End Sub
Public Sub EndEdit() Implements IEditableObject.EndEdit
If Not inEdit Then Return
inEdit = False
backupCopy = Nothing
End Sub
#End Region
#Region "INotifyPropertyChanged"
Public Event PropertyChanged As PropertyChangedEventHandler _
Implements INotifyPropertyChanged.PropertyChanged
Private Sub OnPropertyChanged(ByVal propertyName As String)
RaiseEvent PropertyChanged(Me, _
New PropertyChangedEventArgs(propertyName))
End Sub
#End Region
End Class
Public Class CourseValidationRule
Inherits ValidationRule
Public Overrides Function Validate(ByVal value As Object, _
ByVal cultureInfo As System.Globalization.CultureInfo) _
As ValidationResult
Dim course As Course = _
CType(CType(value, BindingGroup).Items(0), Course)
If course.StartDate > course.EndDate Then
Return New ValidationResult(False, _
"Start Date must be earlier than End Date.")
Else
Return ValidationResult.ValidResult
End If
End Function
End Class
<Window x:Class="DataGridValidation.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DataGridValidation"
Title="DataGrid Validation Example" Height="240" Width="600">
<Grid>
<Grid.Resources>
<local:Courses x:Key="courses"/>
</Grid.Resources>
<DataGrid Name="dataGrid1" FontSize="20" RowHeaderWidth="27"
ItemsSource="{StaticResource courses}"
AutoGenerateColumns="False">
<DataGrid.Resources>
<Style x:Key="errorStyle" TargetType="{x:Type TextBox}">
<Setter Property="Padding" Value="-2"/>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="Background" Value="Red"/>
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Header="Course Name"
Binding="{Binding Name, TargetNullValue=(enter a course name)}"/>
<DataGridTextColumn Header="Course ID"
EditingElementStyle="{StaticResource errorStyle}"
Binding="{Binding Id, ValidatesOnExceptions=True}"/>
<DataGridTextColumn Header="Start Date"
EditingElementStyle="{StaticResource errorStyle}"
Binding="{Binding StartDate, ValidatesOnExceptions=True,
StringFormat=d}"/>
<DataGridTextColumn Header="End Date"
EditingElementStyle="{StaticResource errorStyle}"
Binding="{Binding EndDate, ValidatesOnExceptions=True,
StringFormat=d}"/>
</DataGrid.Columns>
<DataGrid.RowValidationRules>
<local:CourseValidationRule ValidationStep="UpdatedValue"/>
</DataGrid.RowValidationRules>
<DataGrid.RowValidationErrorTemplate>
<ControlTemplate>
<Grid Margin="0,-2,0,-2"
ToolTip="{Binding RelativeSource={RelativeSource
FindAncestor, AncestorType={x:Type DataGridRow}},
Path=(Validation.Errors)[0].ErrorContent}">
<Ellipse StrokeThickness="0" Fill="Red"
Width="{TemplateBinding FontSize}"
Height="{TemplateBinding FontSize}" />
<TextBlock Text="!" FontSize="{TemplateBinding FontSize}"
FontWeight="Bold" Foreground="White"
HorizontalAlignment="Center" />
</Grid>
</ControlTemplate>
</DataGrid.RowValidationErrorTemplate>
</DataGrid>
</Grid>
</Window>
Lásd még
.NET Desktop feedback