WPF DataGrid validation errors not clearing

2019-01-11 02:55发布

So I have a WPF DataGrid, which is bound to an ObservableCollection. The collection has validation on its members, through IDataErrorInfo. If I edit a cell in a way so as to be invalid, and then tab away from it before hitting enter, then come back and make it valid, the cell will stop showing invalid, however, the "!" at the head of the row will still be there, and the ToolTip will reference the previous, invalid value.

14条回答
等我变得足够好
2楼-- · 2019-01-11 03:06

I have used this technique which do away with RowValidationRules and instead use the property validations in a viewmodel. This requires static variables and data annotations :

//uses Prism.MVVM for BindableBase and INotifyDataErrorInfo

private static int _xxStartNo;
private static int _xxEndNo;

// in property getter/setter
private int _startNo;
[CustomValidation(typeof(YourModel), "ValidateStartNoRange")]
public int StartNo
{
    get
       {
          _xxStartNo=_startNo;
          return _startNo;
       }
    set
       {
         .......... 
         ValidateProperty("StartNo") 
       }
}
.......

public static ValidationResult ValidateStartNoRange(int number)
{
   if(number > _xxEndNo) 
   {
       return ValidationResult("Start No must be less than End No.";
   }
   return ValidationResult.Success;
}       
查看更多
倾城 Initia
3楼-- · 2019-01-11 03:08

My solution was to implement custom row validation feedback, similar to this page under the To customize row validation feedback section. The row error then disappears appropriately.

(I also added RowHeaderWidth="20" to the DataGrid definition, to avoid the table shift to the right the first time the exclamation point appears.)

查看更多
疯言疯语
4楼-- · 2019-01-11 03:14

Ok, after some work an alteration of synergetic's solution worked for me, this is how I implemented it:

    <Style x:Key="{x:Type DataGridRowHeader}" TargetType="{x:Type DataGridRowHeader}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate>
                    <Control SnapsToDevicePixels="true"
                 Visibility="{Binding RelativeSource={RelativeSource 
                              AncestorType={x:Type DataGridRow}}, 
                              Path=Item.HasErrors, Converter={StaticResource 
                              BooleanToVisibilityConverter }}"
                 Template="{Binding RelativeSource={RelativeSource 
                            AncestorType={x:Type DataGridRow}}, 
                            Path=ValidationErrorTemplate}" />
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Don't forget to reference the BooleanToVisibilityConverter:

    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>

Just the row style does not (yet) look as good as the default one, I'm working on it.

Edit: Plz help here

查看更多
劫难
5楼-- · 2019-01-11 03:15

I am not using IDataErrorInfo or INotifyDataErrorInfo and my solution was to change my bindings from UpdateSourceTrigger="PropertyChanged" to UpdateSourceTrigger="LostFocus" This was the only thing that

If you are using ValidationRules in your DataGrid column defintion and you need the validation rules to run when ever the property changes (in the UI or the property) look into setting ValidatesOnTargetUpdated="True" on your ValidationRule

XAML Example:

<DataGridTextColumn Header="Name"
    CellStyle="{StaticResource DGCellStyle}"
    ElementStyle="{StaticResource DGTextColValidationStyle}"
    EditingElementStyle="{StaticResource DGTextColEditValidationStyle}">
    <DataGridTextColumn.Binding>
        <Binding Path="Name" UpdateSourceTrigger="LostFocus">
            <Binding.ValidationRules>
                <ValidationResource:YourValidationRule ValidationStep="UpdatedValue" ValidatesOnTargetUpdated="True" />
            </Binding.ValidationRules>
        </Binding>
    </DataGridTextColumn.Binding>
</DataGridTextColumn>
查看更多
我想做一个坏孩纸
6楼-- · 2019-01-11 03:18

In my case, it worked all well and good when we were using the DataGrid WPF3.5 version. We upgraded to 4.0, then it stopped resetting. After searches on SO, google etc, I chanced upon my solution. Setting UpdateSourceTrigger=PropertyChanged on the Binding in the DataGridTextColumn fixed it for me.

I just realised that the red exclamation mark does not clear on setting it to a correct value.

查看更多
Melony?
7楼-- · 2019-01-11 03:19

In my case I had to remove from binding definition

UpdateSourceTrigger=PropertyChanged

For me it works with both of these definitions:

<DataGridTextColumn                                         
Header="Time, min" 
x:Name="uiDataGridTextColumnTime"
Width="Auto"                                            
CellStyle="{StaticResource ResourceKey=DataGridCellText}"                                            
IsReadOnly="False">
<DataGridTextColumn.Binding>
    <Binding Path="fTime" StringFormat="{}{0:0.00}">
        <Binding.ValidationRules>
            <Validation:CellDataInfoValidationRule ValidationStep="UpdatedValue"/>
        </Binding.ValidationRules>
    </Binding>
</DataGridTextColumn.Binding>

And

<DataGridTextColumn                                         
Header="Time, min" 
x:Name="uiDataGridTextColumnTime"
Width="Auto"                                            
CellStyle="{StaticResource ResourceKey=DataGridCellText}"     
Binding="{Binding fTime, StringFormat={}\{0:0.00\}, ValidatesOnDataErrors=True}" 
IsReadOnly="False">

Validation:CellDataInfoValidationRule is custom class & get it here

public class CellDataInfoValidationRule : ValidationRule
{
    public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
    {
        // obtain the bound business object
        BindingExpression expression = value as BindingExpression;
        IDataErrorInfo info = expression.DataItem as IDataErrorInfo;

        // determine the binding path
        string boundProperty = expression.ParentBinding.Path.Path;

        // obtain any errors relating to this bound property
        string error = info[boundProperty];
        if (!string.IsNullOrEmpty(error))
        {
            return new ValidationResult(false, error);
        }

        return ValidationResult.ValidResult;
    }
}

And your data object must implement IDataErrorInfo

查看更多
登录 后发表回答