为什么WPF Style在ToolTip中显示验证错误为TextBox工作但对ComboBox失败?

Mik*_*e B 38 c# data-binding validation wpf styles

我使用一个典型的样式来显示验证错误作为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>
Run Code Online (Sandbox Code Playgroud)

但是当我尝试为这样的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>
Run Code Online (Sandbox Code Playgroud)

我在输出窗口中得到的错误是:

System.Windows.Data错误:17:无法从'(Validation.Errors)'获取'Item []'值(类型'ValidationError')(类型'ReadOnlyObservableCollection`1').BindingExpression:路径=(0)[0] .ErrorContent; DataItem ='ComboBox'(Name ='ownerComboBox'); target元素是'ComboBox'(Name ='ownerComboBox'); target属性是'ToolTip'(类型'Object')ArgumentOutOfRangeException:'System.ArgumentOutOfRangeException:指定的参数超出了有效值的范围.参数名称:index'

奇怪的是,如果我更改任何ComboBox值,它也会尝试在关闭窗口时进行无效的数据库更改(这也是发生绑定错误时)!

无法将值NULL插入列'EmpFirstName',表'OITaskManager.dbo.Employees'; 列不允许空值.INSERT失败.该语句已终止.

简单地通过评论风格完美的每一个作品.我该如何解决?

万一有人需要它,其中一个comboBox'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>
Run Code Online (Sandbox Code Playgroud)

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

Nat*_*lus 105

您收到此错误是因为验证发现没有问题时,Errors集合将返回没有项目,并且以下绑定逻辑失败:

Path=(Validation.Errors)[0].ErrorContent}"
Run Code Online (Sandbox Code Playgroud)

您是通过特定索引访问验证集合.我目前正在研究用于替换此文本的DataTemplate建议.

我喜欢微软在他们的验证模板的标准示例中列出了这一点.

更新所以用以下代码替换上面的代码,绑定逻辑将知道如何处理空的validationresult集合:

Path=(Validation.Errors).CurrentItem.ErrorContent}"
Run Code Online (Sandbox Code Playgroud)

(以下xaml作为评论添加)

<ControlTemplate x:Key="ValidationErrorTemplate" TargetType="Control">
    <StackPanel Orientation="Horizontal">
        <TextBlock Foreground="Red" FontSize="24" Text="*" 
                   ToolTip="{Binding .CurrentItem}">
        </TextBlock>
        <AdornedElementPlaceholder>
        </AdornedElementPlaceholder>
    </StackPanel>
</ControlTemplate>
Run Code Online (Sandbox Code Playgroud)

  • @NathanTregillus很棒的提示.在ControlTemplate上,我不得不使用`ToolTip ="{Binding Path =/ErrorContent}"`否则我只是在工具提示中得到了一个类名. (3认同)
  • @NathanTregillus 非常感谢您的提示!经过几天的……!**但**请更新您的帖子,现在看来使用`/`而不是`.CuttentItem`是正确的!@Alexander 现在看来`ObservableCollection` 也在工作!我对“IEnumerable”和“ObservableCollection”进行了测试。无论如何也感谢您的提示! (2认同)

Alt*_*ung 12

我认为这是最好的方法:

Path=(Validation.Errors)/ErrorContent
Run Code Online (Sandbox Code Playgroud)

/实际上等于CurrentItem@Nathan

就我而言,CurrentItem是不行的.

  • 当然,正确答案也应该更新。 (2认同)