Как я могу отобразить сумму всех ошибок проверки ячейки в ControlTemplate DataGridRow, но только ошибки ячейки при наведении на ячейку? - PullRequest
0 голосов
/ 23 января 2019

У меня есть 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 после ввода недопустимого символа: enter image description here

Вот так выглядит DataGridRow после удаления всех недопустимых символов: enter image description here

-> Красная граница все еще находится вокруг строки, а предупреждающий знак с левой стороны строки все еще виден.

Я тоже это попробовал:

    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

1 Ответ

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

Я отображаю подсказку следующим образом:

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>

Выглядит так: enter image description here

Редактировать: информация добавлена ​​в комментарий

Если вы хотите отобразить список всех ошибок, вам необходимо реализовать интерфейс 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>

Вы сможете получить подсказку обо всех ошибках при наведениилюбая часть строки.

enter image description here

РЕДАКТИРОВАТЬ 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));
}
...