0

我有一个 DataGrid,我使用 . 验证每个单元格的用户输入IDataErrorInfo。当用户输入无效数据时,会为每个单元格显示相应的错误消息。
当我将 ValidationErrorTemplate (controltemplate) 悬停在网格行的左侧时,如何收集和显示所有行的单元格错误消息?

<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="!" />
                    <!--<ToolTip  {Binding RelativeSource={RelativeSourceSelf}, Path=(Validation.Errors)[0].ErrorContent}"/>-->
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="Validation.HasError" Value="true">
        <!--<DataTrigger Binding="{Binding Path=(Validation.HasError), RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGridRow}}" Value="true" >-->
        <!--<DataTrigger Binding="{Binding Path=(Validation.HasError), RelativeSource={RelativeSource  Self}}" Value="true" >-->
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="BorderBrush" Value="Red"/>
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="IsEnabled" Value="True" />
        </Trigger>
        <Trigger Property="Validation.HasError" Value="false">
        <!--<DataTrigger Binding="{Binding Path=(Validation.HasError), RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGridRow}}" Value="false" >-->
        <!--<DataTrigger Binding="{Binding Path=(Validation.HasError), RelativeSource={RelativeSource  Self}}" Value="false" >-->
            <Setter Property="ToolTip" Value="{x:Null}"/>
            <Setter Property="BorderThickness" Value="0"/>
            <Setter Property="BorderBrush" Value="Transparent"/>
            <Setter Property="IsEnabled" Value="True" />
        </Trigger>
    </Style.Triggers>
</Style>

2019-01-25 更新: 我的风格定义了错误的单元格:

<Style x:Key="textBlockErrStyle" TargetType="{x:Type TextBlock}">
    <Style.Triggers>
        <DataTrigger Binding="{Binding Path=(Validation.HasError), RelativeSource={RelativeSource Self}}" Value="false" >
            <Setter Property="ToolTip" Value="{x:Null}"/>
        </DataTrigger>
        <DataTrigger Binding="{Binding (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)[0].ErrorContent}"/>
            <!--<Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=RawTag.ErrorList, Converter={StaticResource conv:StringToListConverter}}"/>-->
        </DataTrigger>
    </Style.Triggers>
</Style>

2019-02-18 更新:

这是输入无效字符后 DataGridRow 的样子: 在此处输入图像描述

这是删除所有无效字符后 DataGridRow 的样子: 在此处输入图像描述

--> 红色边框仍在该行周围,该行左侧的警告标志仍然可见。

我也试过这个:

    public void RemoveError(string propertyName, bool notify = true)
    {
        if (ErrorList.ContainsKey(propertyName))
        {
            ErrorList.Remove(propertyName);
            HasErrors = ErrorList.Count > 0;
            //NotifyErrorsChanged(propertyName);
            OnPropertyChanged(propertyName);
            OnPropertyChanged("GetAllErrors");
        }
        if (notify) ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
    }

...尽管我OnPropertyChange在模型类的每个设置器中都使用了。错误列表为空,但边框和警告符号保留。

2019-02-19 更新:

我对 INotfiyPropertyChanged 接口的实现:

    #region INotifyPropertyChanged

    /// <summary>
    /// Handler to register for property changed event
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;

    /// <summary>
    /// Method to invoke the property change event
    /// </summary>
    /// <param name="propertyName">The name of the changed property</param>
    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion
4

1 回答 1

1

我这样显示工具提示:

ToolTip="{Binding Path=/ErrorContent}"

这是整个模板。

<ControlTemplate x:Key="ValidationTemplate">
    <Grid>
        <Border BorderBrush="red" BorderThickness="1" Background="#11FF0000" Opacity="0.5" IsHitTestVisible="False" x:Name="errorBorder"/>
        <AdornedElementPlaceholder x:Name="placeholder" ToolTip="{Binding Path=/ErrorContent}" />
        <Ellipse DockPanel.Dock="Right"
                                ToolTip="{Binding Path=/ErrorContent}"
                                HorizontalAlignment="Left"
                                VerticalAlignment="Top"
                                Width="15" Height="15"
                                Margin="-15,0,0,0"
                                StrokeThickness="1" Fill="Red" >
            <Ellipse.Stroke>
                <LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
                    <GradientStop Color="#FFFA0404" Offset="0"/>
                    <GradientStop Color="#FFC9C7C7" Offset="1"/>
                </LinearGradientBrush>
            </Ellipse.Stroke>
        </Ellipse>
        <TextBlock Text="!" Foreground="White" FontWeight="Bold" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="-10,-1"
                                ToolTip="{Binding Path=/ErrorContent}" TextBlock.LineHeight="15.5"/>
    </Grid>
</ControlTemplate>

看起来像这样: 在此处输入图像描述

编辑:每条评论添加的信息

如果要显示所有错误的列表,则需要为INotifyDataErrorInfo类实现接口。然后做这样的事情:

public bool HasErrors { get; set; } = false;
public Dictionary<string, string> ErrorList = new Dictionary<string, string>();
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
public void NotifyErrorsChanged(string PropertyName) { ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(PropertyName)); }

public IEnumerable GetErrors(string propertyName)
{
    if (!HasErrors || propertyName == null) return null;
    if (ErrorList.Keys.Contains(propertyName)) return new List<string>() { ErrorList[propertyName] };
    if (propertyName != "GetAllErrors") NotifyPropertyChanged("GetAllErrors");
    return new List<string>();
}

public string GetAllErrors
{
    get
    {
        if (!HasErrors) return null;
        int count = 1;
        var errors= "Errors:";
        foreach (var e in ErrorList)
        {
            errors += "\n" + count++ + ". " + e.Value;
        }
        return errors;
    }
}

然后在数据网格的 RowStyle 中设置工具提示,如下所示:

<DataGrid.RowStyle>
    <Style TargetType="{x:Type DataGridRow}">
        <Setter Property="ToolTip" Value="{Binding GetAllErrors}"/>
    </Style>
</DataGrid.RowStyle>

您应该能够通过悬停该行的任何部分来获得所有错误的工具提示。

在此处输入图像描述

编辑 2: 我添加了自己的方法来消除错误。

public void RemoveError(string PropertyName, bool Notify = true)
{
    if (ErrorList.ContainsKey(PropertyName))
    {
        ErrorList.Remove(PropertyName);
        HasErrors = ErrorList.Count > 0;
    }
    if (Notify) ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(PropertyName));
}

public void ClearErrors()
{
    var removalList = new Dictionary<string, string>(ErrorList);
    ErrorList.Clear();
    HasErrors = false;
    foreach (var propertyName in removalList.Keys) ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
}
于 2019-01-23T13:23:35.687 回答