我能够显示数据网格中一个特定单元格的验证错误,但是如果存在个以上验证错误,我不知道该怎么做。例如,我有十列,并且在两个或多个单元格中存在验证错误。
目前,我已经在App.xaml包含的单独文件中将样式定义为ResourceDictionary。
样式:
<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">
<!--<DataTrigger Binding="{Binding Path=(Validation.HasError), RelativeSource={RelativeSource AncestorType=DataGridRow}}" Value="true" >-->
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush" Value="Red"/>
<Setter Property="IsEnabled" Value="True" />
<!--<Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors).Currentitem.ErrorContent}"/>-->
<Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="cycleErrStyle" TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=(Validation.HasError), RelativeSource={RelativeSource AncestorType=DataGridRow}}" Value="true" >
<Setter Property="Background" Value="Red" />
<Setter Property="Foreground" Value="White" />
</DataTrigger>
</Style.Triggers>
</Style>
模型类:
public class RawTag : IDataErrorInfo, INotifyPropertyChanged
{
private readonly int hash;
private string tagName;
private string cycle;
private string source;
public RawTag()
{
hash = GetHashCode();
}
public RawTag(string tagName, string cycle, string source)
{
TagName = tagName;
Cycle = cycle;
Source = source;
hash = GetHashCode();
}
public string TagName
{
get => tagName;
set
{
if (value == tagName) return;
tagName = value;
OnPropertyChanged();
}
}
// should be an integer but any entered value shall be accepted
public string Cycle
{
get => cycle;
set
{
if (value.Equals(cycle))
{
return;
}
cycle = value;
OnPropertyChanged();
}
}
public string Source
{
get => source;
set
{
if (value == source) return;
source = value;
OnPropertyChanged();
}
}
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
{
// apply property level validation rules
if (columnName == "TagName")
{
if (string.IsNullOrEmpty(TagName))
return "Name cannot be null or empty";
}
if (columnName == "Cycle")
{
if (!int.TryParse(Cycle.ToString(), out int i))
return "Cycle should be an integer value.";
}
if (columnName == "Source")
{
if (string.IsNullOrEmpty(Source))
return "Source must not be empty";
}
return "";
}
}
public override string ToString()
{
return "TagName: " + TagName + " Cycle: " + Cycle + " Source: " + Source;
}
public bool IsDirty()
{
return hash != GetHashCode();
}
protected bool Equals(RawTag other)
{
return string.Equals(TagName, other.TagName) && string.Equals(Cycle, other.Cycle) && string.Equals(Source, other.Source);
//return string.Equals(TagName, other.TagName) && Cycle == other.Cycle && string.Equals(Source, other.Source);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((RawTag)obj);
}
public override int GetHashCode()
{
unchecked
{
var hashCode = (TagName != null ? TagName.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (Cycle != null ? Cycle.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (Source != null ? Source.GetHashCode() : 0);
return hashCode;
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
我的验证班:
public class CycleValidationRule : ValidationRule
{
public override ValidationResult Validate(object value,
System.Globalization.CultureInfo cultureInfo)
{
BindingGroup group = (BindingGroup)value;
StringBuilder error = null;
foreach (var item in group.Items)
{
IDataErrorInfo info = item as IDataErrorInfo;
if (info != null)
{
if (!string.IsNullOrEmpty(info.Error))
{
if (error == null)
{
error = new StringBuilder();
}
error.Append((error.Length != 0 ? ", " : "") + info.Error);
}
}
}
if (error != null)
return new ValidationResult(false, error.ToString());
else
return new ValidationResult(true, "");
}
}
验证后,我希望突出显示有故障的单元格,将鼠标悬停在有故障的单元格上时,仅在该工具提示中显示该特定单元格/字段的验证错误的错误消息。
更新2019-01-17:
必须有一种方法将IDataErrorInfo
与ValidationRules
组合在一起,以使来自IDataErrorInfo
的错误消息进入ValidationRule
(目前运行良好)可以将错误消息与来自ValidationRule
的错误消息进行组合,并将错误消息的总和提供给GUI(WPF)。 ...但是工具提示中仅显示来自IDataErrorInfo
的错误消息。
答案 0 :(得分:0)
ValueAnimator anim = ValueAnimator.ofInt(viewToIncreaseHeight.getMeasuredHeight(), -100);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int val = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams = viewToIncreaseHeight.getLayoutParams();
layoutParams.height = val;
viewToIncreaseHeight.setLayoutParams(layoutParams);
}
});
anim.setDuration(DURATION);
anim.start();
不支持每个属性多个验证错误。 .NET Framework 4.5中引入的更新的INotifyDataErrorInfo接口。
有一个示例,说明如何实现here。
您可以使用IDataErrorInfo
来显示错误消息。请查看我的答案here作为示例。