Почему стиль WPF для отображения ошибок проверки во всплывающей подсказке работает для TextBox, но не работает для ComboBox? - PullRequest
38 голосов
/ 14 февраля 2010

Я использую типичный стиль для отображения ошибок проверки в качестве всплывающей подсказки из IErrorDataInfo для текстового поля, как показано ниже, и он отлично работает.

    <Style TargetType="{x:Type TextBox}">
        <Style.Triggers>
            <Trigger Property="Validation.HasError" Value="true">
                <Setter Property="ToolTip"
                Value="{Binding RelativeSource={RelativeSource Self},
            Path=(Validation.Errors)[0].ErrorContent}"/>
            </Trigger>
        </Style.Triggers>
    </Style>

Но когда я пытаюсь сделать то же самое для ComboBox, как это, он терпит неудачу

    <Style TargetType="{x:Type ComboBox}">
        <Style.Triggers>
            <Trigger Property="Validation.HasError" Value="true">
                <Setter Property="ToolTip"
                Value="{Binding RelativeSource={RelativeSource Self},
            Path=(Validation.Errors)[0].ErrorContent}"/>
            </Trigger>
        </Style.Triggers>
    </Style>

Ошибка, которую я получаю в окне вывода:

System.Windows.Data Ошибка: 17: Невозможно получить значение «Item []» (тип «ValidationError») из «(Validation.Errors)» (тип «ReadOnlyObservableCollection`1 '). BindingExpression: Путь = (0) [0] .ErrorContent; DataItem = 'ComboBox' (Name = 'ownerComboBox'); целевой элемент - «ComboBox» (Name = «ownerComboBox»); Свойство target - «ToolTip» (тип «Object»). ArgumentOutOfRangeException: «System.ArgumentOutOfRangeException: указанный аргумент находится вне диапазона допустимых значений. Имя параметра: index '

Как ни странно, он также пытается внести недопустимые изменения в базу данных, когда я закрываю окно, если я изменяю какие-либо значения ComboBox (это также происходит при возникновении ошибки привязки) !!!

Невозможно вставить значение NULL в столбец «EmpFirstName», таблица «OITaskManager.dbo.Employees»; столбец не допускает пустых значений. Вставить не удается. Заявление было прекращено.

Просто, комментируя стиль, все работает идеально. Как мне это исправить?

На всякий случай, если кому-то это нужно, один из комбоБоксов: xaml:

<ComboBox ItemsSource="{Binding Path=Employees}" 
                  SelectedValuePath="EmpID"                       
                  SelectedValue="{Binding Path=SelectedIssue.Employee2.EmpID,
                     Mode=OneWay, ValidatesOnDataErrors=True}" 
                  ItemTemplate="{StaticResource LastNameFirstComboBoxTemplate}"
                  Height="28" Name="ownerComboBox" Width="120" Margin="2" 
                  SelectionChanged="ownerComboBox_SelectionChanged" />


<DataTemplate x:Key="LastNameFirstComboBoxTemplate">
    <TextBlock> 
         <TextBlock.Text> 
             <MultiBinding StringFormat="{}{1}, {0}" > 
                   <Binding Path="EmpFirstName" /> 
                   <Binding Path="EmpLastName" /> 
             </MultiBinding>
         </TextBlock.Text>
    </TextBlock>
</DataTemplate>

SelectionChanged: (я планирую реализовать командование в ближайшее время, но, поскольку это мой первый проект WPF, я еще не полностью выполнил MVVM. Я пытаюсь взять вещи небольшими кусочками)

// This is done this way to maintain the DataContext Integrity 
// and avoid an error due to an Object being "Not New" in Linq-to-SQL
private void ownerComboBox_SelectionChanged(object sender, 
                                            SelectionChangedEventArgs e)
{
    Employee currentEmpl = ownerComboBox.SelectedItem as Employee;
    if (currentEmpl != null && 
        currentEmpl != statusBoardViewModel.SelectedIssue.Employee2)
    {
        statusBoardViewModel.SelectedIssue.Employee2 = currentEmpl;
    }
}

Ответы [ 6 ]

105 голосов
/ 02 ноября 2010

Вы получаете эту ошибку, потому что, когда при проверке обнаруживается, что проблем нет, коллекция Errors возвращается без элементов, и следующая логика привязки завершается неудачей:

Path=(Validation.Errors)[0].ErrorContent}"

вы получаете доступ к коллекции проверки по определенному индексу. В настоящее время я работаю над предложением DataTemplate для замены этого текста.

Мне нравится, что Microsoft перечислила это в своем стандартном примере шаблона проверки.

update , поэтому замените приведенный выше код следующим, и логика привязки будет знать, как обращаться с пустой коллекцией результата проверки:

Path=(Validation.Errors).CurrentItem.ErrorContent}"

(следующий xaml был добавлен в качестве комментария)

<ControlTemplate x:Key="ValidationErrorTemplate" TargetType="Control">
    <StackPanel Orientation="Horizontal">
        <TextBlock Foreground="Red" FontSize="24" Text="*" 
                   ToolTip="{Binding .CurrentItem}">
        </TextBlock>
        <AdornedElementPlaceholder>
        </AdornedElementPlaceholder>
    </StackPanel>
</ControlTemplate>
10 голосов
/ 25 апреля 2018

Я думаю, что это лучший способ:

Path=(Validation.Errors)/ErrorContent

/ фактически равно CurrentItem @ Nathan

В моем случае, CurrentItem - это не ход.

2 голосов
/ 20 апреля 2010

Попробуйте преобразователь для преобразования в многострочную строку как описано здесь

1 голос
/ 12 ноября 2018

В моем случае я получал это исключение, когда пытался применить решение @ Nation Tregillus ':

Не удается разрешить свойство CurrentItem в контексте данных типа 'System.Collections.ObjectModel.ReadOnlyObservableCollection'

Итак, вместо этого я выбрал решение @ Altiano Gerung , где мой код оказался:

<ControlTemplate x:Key="ValidationErrorTemplate">
    <DockPanel Margin="5,0,36,0">
        <StackPanel Orientation="Horizontal" VerticalAlignment="Top" DockPanel.Dock="Right"
                    Margin="5,0,36,0"
                    ToolTip="{Binding ElementName=ErrorAdorner, Path=AdornedElement.(Validation.Errors)/ErrorContent}"
                    ToolTipService.ShowDuration="300000"
                    ToolTipService.InitialShowDelay="0"
                    ToolTipService.BetweenShowDelay="0"
                    ToolTipService.VerticalOffset="-75"
                    >
1 голос
/ 21 июня 2010

Я видел код, который вы используете, размещен в нескольких местах, но мне кажется странным, что

Path=(Validation.Errors)[0].ErrorContent}

не поднимает никаких красных флажков. Но я также новичок в WPF и, возможно, есть какой-то секрет, чтобы заставить это работать в каждом случае.

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

0 голосов
/ 30 ноября 2018

CurrentItem у меня тоже не работал @ Ответ Наттана сработал для моей ситуации, когда у меня есть собственный ресурс textBox. Спасибо, Натан, я потратил час на это.

<Style.Triggers>
  <Trigger Property="Validation.HasError" Value="true">
    <Setter Property="ToolTip"
        Value="{Binding RelativeSource={x:Static RelativeSource.Self},
        Path=(Validation.Errors)/ErrorContent}" />
  </Trigger>
</Style.Triggers>
...