Как очистить использование шаблона ошибки после исправления ошибочных значений ячеек? - PullRequest
0 голосов
/ 18 января 2019

У меня есть DataGrid, в котором значения ячеек проверены. Для визуализации недопустимых значений у меня есть стиль, если для свойства Validation.HasError установлено значение true:

<Style TargetType="{x:Type DataGridRow}">
    <Setter Property="FontSize" Value="16"/>
    <Setter Property="FontFamily" Value="ArialMT"/>
    <Setter Property="Height" Value="24"/>
    <Setter Property="VerticalAlignment" Value="Center"/>
    <Setter Property="ValidationErrorTemplate">
        <Setter.Value>
            <ControlTemplate>
                <Grid>
                    <Ellipse Width="12" Height="12" Fill="Red" Stroke="Black" StrokeThickness="0.5"/>
                    <TextBlock FontWeight="Bold" Padding="4,0,0,0" Margin="0" VerticalAlignment="Top" Foreground="White" Text="!" />
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="Validation.HasError" Value="true">
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="BorderBrush" Value="Red"/>
            <Setter Property="IsEnabled" Value="True" />
        </Trigger>
        <Trigger Property="Validation.HasError" Value="false">
            <Setter Property="ToolTip" Value=""/>
            <Setter Property="BorderThickness" Value="0"/>
            <Setter Property="BorderBrush" Value="Transparent"/>
        </Trigger>
    </Style.Triggers>
</Style>

<Style x:Key="textBlockErrStyle" TargetType="{x:Type TextBlock}">
    <Style.Triggers>
        <DataTrigger Binding="{Binding Path=(Validation.HasError), RelativeSource={RelativeSource Self}}" Value="true" >
            <Setter Property="Background" Value="Red" />
            <Setter Property="Foreground" Value="White" />
            <Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)/ErrorContent}"/>
        </DataTrigger>
    </Style.Triggers>
</Style>

Я реализовал ValidationRule (я хотел объединить его с IDataErrorInfo):

public class CycleValidationRule : ConfigToolValidationRule
{
    public override ValidationResult Validate(object value,
        System.Globalization.CultureInfo cultureInfo)
    {
        BindingGroup group = (BindingGroup)value;
        StringBuilder error = null;
        foreach (var item in group.Items)
        {
            if (!(item is IDataErrorInfo))
            {
                continue;
            }
            error = (StringBuilder)base.Validate(item, cultureInfo).ErrorContent;
            IDataErrorInfo info = item as IDataErrorInfo;

            if (info != null)
            {
                if (error == null)
                {
                    error = new StringBuilder();
                }

                if (!string.IsNullOrEmpty(info.Error))
                {
                    error.Append((error.Length != 0 ? Environment.NewLine : "") +  info.Error);
                }
            }
        }

        if (!string.IsNullOrEmpty(error?.ToString()) && !string.IsNullOrWhiteSpace(error?.ToString()) )
            return new ValidationResult(true, error.ToString());
        else
            return new ValidationResult(true, "");

    }
}

... и реализация IDataErrorInfo в классе модели:

// What is this method for at all???
string IDataErrorInfo.Error
{
    get
    {
        StringBuilder error = new StringBuilder();

        //if (string.IsNullOrEmpty(TagName))
        //{
        //    error.Append("Name cannot be null or empty");
        //}
        //if (!int.TryParse(Cycle.ToString(), out int i))
        //{
        //    error.Append("Cycle should be an integer value.");
        //}

        return error.ToString();
    }
}

string IDataErrorInfo.this[string columnName]
{
    get
    {
        StringBuilder errors = new StringBuilder();
        // apply property level validation rules
        if (columnName == "TagName")
        {
            if (string.IsNullOrEmpty(TagName))
            {
                //return "Name cannot be null or empty";
                errors.Append((errors.Length != 0 ? Environment.NewLine : "") + "Tag name cannot be null or empty.");
            }
            if(TagName.Contains(";"))
            {
                errors.Append((errors.Length != 0 ? Environment.NewLine : "") + "Tag name may not contain the character ';'.");
            }
        }

        if (columnName == "Cycle")
        {
            if (!int.TryParse(Cycle.ToString(), out int i))
            {
                //return "Cycle should be an integer value.";
                errors.Append((errors.Length != 0 ? Environment.NewLine : "") + "Cycle should be an integer value.");
            }
            if (Cycle.Contains(";"))
            {
                errors.Append((errors.Length != 0 ? Environment.NewLine : "") + "Cycle may not contain the character ';'.");
            }
        }

        if (columnName == "Source")
        {
                //return "Source must not be empty";
            if (string.IsNullOrEmpty(Source))
            {
                errors.Append((errors.Length != 0 ? Environment.NewLine : "") + "Source must not be empty.");
            }
            if (Source.Contains(";"))
            {
                errors.Append((errors.Length != 0 ? Environment.NewLine : "") + "Source may not contain the character ';'.");
            }
        }

        return errors.ToString();
    }
}

Определение DataGrid в XAML (извлечение):

    <DataGrid.RowValidationRules>
        <local:CycleValidationRule ValidationStep="UpdatedValue" />
    </DataGrid.RowValidationRules>
    <DataGrid.Columns>
        <DataGridTextColumn x:Name="TagName" Header="Tag name" Width="*" 
                                Binding="{Binding Mode=TwoWay, Path=RawTag.TagName, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"
                                ElementStyle="{StaticResource ResourceKey=textBlockErrStyle}"/>
        <DataGridTextColumn x:Name="TagCycle" Header="Cycle" 
                                Binding="{Binding Mode=TwoWay, Path=RawTag.Cycle, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" 
                                ElementStyle="{StaticResource ResourceKey=textBlockErrStyle}">
        </DataGridTextColumn>
        <DataGridTextColumn x:Name="TagSource" Header="Source" Width="*" 
                                Binding="{Binding Mode=TwoWay, Path=RawTag.Source, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, NotifyOnValidationError=True}"
                                ElementStyle="{StaticResource ResourceKey=textBlockErrStyle}"/>
        </DataGridTextColumn>
    <DataGrid.Columns>

Отображение случая ошибки работает хорошо, но строка не отображается в обычном стиле, когда неверные значения были исправлены. Что мне нужно сделать, чтобы отобразить строку в стандартном стиле?

1 Ответ

0 голосов
/ 18 января 2019

Попробуйте удалить UpdateSourceTrigger=PropertyChanged из привязок, например ::

<DataGridTextColumn x:Name="TagName" Header="Tag name" Width="*" 
                    Binding="{Binding Mode=TwoWay, Path=RawTag.TagName, ValidatesOnDataErrors=True}"
                    ElementStyle="{StaticResource ResourceKey=textBlockErrStyle}"/>

DataGrid фиксирует значения построчно.

...