Я новичок ie в WPF, и я изо всех сил пытаюсь проверить DataGrid с помощью FluentValidation, что я пытаюсь проверить каждую строку в Datagrid, проблема в том, что некоторые строки, хотя они действительны, это показывает, что они не действительны
вот скриншот странного поведения DataGrid
снимок экрана
вот код, который я использую
класс
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;
}
}
Validator
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" );
}
}
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;
}
}