У меня есть 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>
Отображение случая ошибки работает хорошо, но строка не отображается в обычном стиле, когда неверные значения были исправлены.
Что мне нужно сделать, чтобы отобразить строку в стандартном стиле?