为什么WPF样式在ToolTip中显示验证错误,为TextBox工作但ComboBox失败? [英] Why does WPF Style to show validation errors in ToolTip work for a TextBox but fails for a ComboBox?

查看:373
本文介绍了为什么WPF样式在ToolTip中显示验证错误,为TextBox工作但ComboBox失败?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用典型的样式来显示验证错误,作为IErrorDataInfo的文本框的工具提示,如下所示,它的工作正常。

 < Style TargetType ={x:Type TextBox}> 
< Style.Triggers>
< Trigger Property =Validation.HasErrorValue =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.HasErrorValue =true>
< Setter Property =ToolTip
Value ={Binding RelativeSource = {RelativeSource Self},
Path =(Validation.Errors)[0] .ErrorContent}/>
< / Trigger>
< /Style.Triggers>
< / Style>

输出窗口中出现的错误是:


$ b $ System.Windows.Data错误:17:无法从'(Validation.Errors)'(类型'ReadOnlyObservableCollection`1')获取'Item []'值(类型'ValidationError')。 BindingExpression:Path =(0)[0] .ErrorContent; DataItem ='ComboBox'(Name ='ownerComboBox');目标元素是'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 =28Name =ownerComboBoxWidth =120Margin =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,我正在尝试用小中型叮咬的东西)

  //这样做了方法来维护DataContext Integrity 
//并避免在Linq-to-SQL中的对象为Not New的错误
private void ownerComboBox_SelectionChanged(object sender,
SelectionChangedEventArgs e)
{
Employee currentEmpl = ownerComboBox.SelectedItem作为Employee;
if(currentEmpl!= null&&$&
currentEmpl!= statusBoardViewModel.SelectedIssue.Employee2)
{
statusBoardViewModel.SelectedIssue.Employee2 = currentEmpl;
}
}


解决方案

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

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

我正在使用DataTemplate建议来替换这个文本。




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



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

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

(以下是xaml添加为评论)

 < ControlTemplate x:Key =验证ErrorTemplateTargetType =Control> 
< StackPanel Orientation =Horizo​​ntal>
< TextBlock Foreground =RedFontSize =24Text =*
ToolTip ={Binding .CurrentItem}>
< / TextBlock>
< AdornedElementPlaceholder>
< / AdornedElementPlaceholder>
< / StackPanel>
< / ControlTemplate>


I am using a typical Style to display validation errors as a tooltip from IErrorDataInfo for a textbox as shown below and it works fine.

    <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>

But when i try to do the same thing for a ComboBox like this it fails

    <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>

The error I get in the output window is:

System.Windows.Data Error: 17 : Cannot get 'Item[]' value (type 'ValidationError') from '(Validation.Errors)' (type 'ReadOnlyObservableCollection`1'). BindingExpression:Path=(0)[0].ErrorContent; DataItem='ComboBox' (Name='ownerComboBox'); target element is 'ComboBox' (Name='ownerComboBox'); target property is 'ToolTip' (type 'Object') ArgumentOutOfRangeException:'System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.Parameter name: index'

Oddly it also attempts to make invalid Database changes when I close the window if I change any ComboBox values (This is also when the binding error occurs)!!!

Cannot insert the value NULL into column 'EmpFirstName', table 'OITaskManager.dbo.Employees'; column does not allow nulls. INSERT fails. The statement has been terminated.

Simply by commenting the style out everyting works perfectly. How do I fix this?

Just in case anyone needs it one of the comboBox' xaml follows:

<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: (I do plan to implement commanding before long but, as this is my first WPF project I have not gone full MVVM yet. I am trying to take things in small-medium sized bites)

// 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;
    }
}

解决方案

Your getting this error because when you validation finds that there are no issues, the Errors collection returns with no items, and the following binding logic fails:

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

you are accessing the validation collection by a specific index. I'm currently working on a DataTemplate Suggestion for replacing this text.

I love that Microsoft listed this in their standard example of a validation template.

update so replace the code above with the following, and the binding logic will know how to handle the empty validationresult collection:

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

(following xaml was added as a comment)

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

这篇关于为什么WPF样式在ToolTip中显示验证错误,为TextBox工作但ComboBox失败?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆