C# 使用fluentvalidation验证datagrid时出现问题
我是WPF的新手,我正在努力使用FluentValidation验证DataGrid 我试图验证Datagrid中的每一行 问题是有些行即使有效,但表明它们无效 下面是DataGrid奇怪行为的屏幕截图 这是我正在使用的代码C# 使用fluentvalidation验证datagrid时出现问题,c#,wpf,fluentvalidation,C#,Wpf,Fluentvalidation,我是WPF的新手,我正在努力使用FluentValidation验证DataGrid 我试图验证Datagrid中的每一行 问题是有些行即使有效,但表明它们无效 下面是DataGrid奇怪行为的屏幕截图 这是我正在使用的代码 阶级 public class DetailFacture : INotifyPropertyChanged, IDataErrorInfo , IEditableObject { private DetailFactureValidator _detailFactur
- 阶级
public class DetailFacture : INotifyPropertyChanged, IDataErrorInfo , IEditableObject { private DetailFactureValidator _detailFactureValidator; private string _libellePiece; private decimal _montantHT; private decimal _tauxTVA; private string _compteCharge; private string _compteTva; private string _codeTva; public DetailFacture ( ) { _detailFactureValidator = new DetailFactureValidator( ); } public string LibellePiece { get { return _libellePiece; } set { _libellePiece = value; OnPropertyChanged( "LibellePiece" ); } } public decimal MontantHT { get { return _montantHT; } set { _montantHT = value; OnPropertyChanged( "MontantHT" ); } } public decimal TauxTVA { get { return _tauxTVA; } set { _tauxTVA = value; OnPropertyChanged( "TauxTVA" ); } } public string CompteCharge { get { return _compteCharge; } set { _compteCharge = value; OnPropertyChanged( "CompteCharge" ); } } public string CompteTva { get { return _compteTva; } set { _compteTva = value; OnPropertyChanged( "CompteTva" ); } } public string CodeTva { get { return _codeTva; } set { _codeTva = value; OnPropertyChanged( "CodeTva" ); } } public string Error { get { if ( _detailFactureValidator != null ) { var results = _detailFactureValidator.Validate( this ); if ( results != null && results.Errors.Any( ) ) { var errors = string.Join( Environment.NewLine , results.Errors.Select( x => x.ErrorMessage ).ToArray( ) ); return errors; } } return string.Empty; } } public string this[ string columnName ] { get { var firstOrDefault = _detailFactureValidator.Validate( this ).Errors.FirstOrDefault( lol => lol.PropertyName == columnName ); if ( firstOrDefault != null ) return _detailFactureValidator != null ? firstOrDefault.ErrorMessage : ""; return ""; } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged ( string propertyName ) { PropertyChanged?.Invoke( this , new PropertyChangedEventArgs( propertyName ) ); } private DetailFacture backupCopy; private bool inEdit; public void BeginEdit ( ) { if ( inEdit ) return; inEdit = true; backupCopy = this.MemberwiseClone( ) as DetailFacture; } public void CancelEdit ( ) { if ( !inEdit ) return; inEdit = false; this.CodeTva = backupCopy.CodeTva; this.CompteCharge = backupCopy.CompteCharge; this.CompteTva = backupCopy.CompteTva; this.LibellePiece = backupCopy.LibellePiece; this.MontantHT = backupCopy.MontantHT; this.TauxTVA = backupCopy.TauxTVA; } public void EndEdit ( ) { if ( !inEdit ) return; inEdit = false; backupCopy = null; } }
- 验证器
public class DetailFactureValidator : AbstractValidator<DetailFacture> { public DetailFactureValidator ( ) { RuleFor( det => det.CodeTva ).NotNull( ).WithMessage( "CodeTva ne doit pas être vide" ) .ExclusiveBetween("32" , "44").WithMessage("Code Tva doit etre entre 32 et 44") .Matches( @"\w*" ).WithMessage( "CodeTva n'est pas une chaîne de caractères" ); RuleFor( det => det.CompteCharge ).NotNull( ).WithMessage( "CompteCharge ne doit pas être vide" ) .Matches( @"\w*" ).WithMessage( "CompteCharge n'est pas une chaîne de caractères" ); RuleFor( det => det.CompteTva ).NotNull( ).WithMessage( "CompteTva ne doit pas être vide" ) .Matches( @"\w*" ).WithMessage( "CompteTva n'est pas une chaîne de caractères" ); RuleFor( det => det.LibellePiece ).NotNull( ).WithMessage( "LibellePiece ne doit pas être vide" ) .Matches( @"\w*" ).WithMessage( "LibellePiece n'est pas une chaîne de caractères" ); } }
public类DetailFactureValidator:AbstractValidator { 公共详细信息制造商验证程序() { RuleFor(det=>det.CodeTva).NotNull().WithMessage(“CodeTva-ne-doit-pasêvide”) “32”、“44”之间的排他性信息(“代码Tva doit etre entre 32 et 44”) .Matches(@“\w*”)。带有消息(“CodeTva n'est pas une chaîne de caractères”); RuleFor(det=>det.CompteCharge).NotNull().WithMessage(“CompteCharge ne doit pasêvide”) .Matches(@“\w*”)。带有消息(“CompteCharge n'est pas une chaîne de caractères”); RuleFor(det=>det.CompteTva).NotNull().WithMessage(“CompteTva ne doit pasêvide”) .Matches(@“\w*”)。带有消息(“CompteTva n'est pas une chaîne de caractères”); RuleFor(det=>det.libellepeate).NotNull().WithMessage(“libellepeate ne doit pasêvide”) .Matches(@“\w*”)。带有消息(“诽谤是不可能的”); } }
- Xaml
- Xaml.cs
public部分类FormulaireUC:UserControl
{
私有可观察收集工厂明细表;
公共处方
{
初始化组件();
grilly.ItemsSource=制造商详细信息列表;
}
}
我建议您尝试将问题分为两个单独的问题。首先,确保规则在单独的测试控制台应用程序中按照您的需要工作。其次,检查代码在运行时接收到的数据网格值。可能绑定错误,或者新输入的数据没有达到您期望的变量。感谢您的回答,我通过将这一行添加到我的XAML代码中解决了这个问题``谢谢您的评论。把你的评论放在上面(说明你是如何解决问题的)作为答案会很好。这将让人们知道你是如何解决问题的,并将问题标记为“已回答”。
<UserControl.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>
<Style TargetType="DataGridCell">
<Setter Property="Margin" Value="0"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="BorderThickness" Value="0"/>
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="DataGridCell_PreviewMouseLeftButtonDown" />
</Style>
<Style TargetType="{x:Type DataGridRow}">
<Setter Property="ValidationErrorTemplate">
<Setter.Value>
<ControlTemplate>
<Image Source="/Images/Alerte.png" ToolTip="{Binding RelativeSource={ RelativeSource FindAncestor, AncestorType={x:Type DataGridRow}}, Path=(Validation.Errors)[0].ErrorContent}" Margin="0" Width="11" Height="11" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<DataGrid x:Name="grille" Grid.ColumnSpan="2" CanUserAddRows="True" ItemsSource="{Binding FactureDetailList, Mode=TwoWay ,ValidatesOnDataErrors=True,ValidatesOnNotifyDataErrors=True,UpdateSourceTrigger=PropertyChanged}" AutoGenerateColumns="False" Background="#FF06C257" BorderBrush="#FF02401D" Foreground="#FF929292" BorderThickness="0" CanUserResizeColumns="False" >
<DataGrid.Columns>
<DataGridTextColumn Header="Libelle Piece" EditingElementStyle="{StaticResource errorStyle}" Binding="{Binding LibellePiece, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
<DataGridTextColumn Header="Montant HT" EditingElementStyle="{StaticResource errorStyle}" Binding="{Binding MontantHT, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
<DataGridTextColumn Header="Taux TVA" EditingElementStyle="{StaticResource errorStyle}" Binding="{Binding TauxTVA, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
<DataGridTextColumn Header="Compte Charge" EditingElementStyle="{StaticResource errorStyle}" Binding="{Binding CompteCharge, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
<DataGridTextColumn Header="Compte Tva" EditingElementStyle="{StaticResource errorStyle}" Binding="{Binding CompteTva, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
<DataGridTextColumn Header="Code Tva" EditingElementStyle="{StaticResource errorStyle}" Binding="{Binding CodeTva, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
</DataGrid.Columns>
</DataGrid>
public partial class FormulaireUC : UserControl
{
private ObservableCollection<DetailFacture> FactureDetailList;
public FormulaireUC ( )
{
InitializeComponent( );
grille.ItemsSource = FactureDetailList;
}
}