簡體   English   中英

為什么 WPF 樣式在 ToolTip 中顯示驗證錯誤適用於文本框,但無法用於組合框?

[英]Why does WPF Style to show validation errors in ToolTip work for a TextBox but fails for a ComboBox?

我正在使用典型的樣式將驗證錯誤顯示為來自 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:無法從“(Validation.Errors)”(類型“ReadOnlyObservableCollection`1”)獲取“Item[]”值(類型“ValidationError”)。 BindingExpression:Path=(0)[0].ErrorContent; DataItem='ComboBox' (Name='ownerComboBox'); 目標元素是 'ComboBox' (Name='ownerComboBox'); 目標屬性是“工具提示”(類型“對象”)ArgumentOutOfRangeException:'System.ArgumentOutOfRangeException:指定的參數超出了有效值的范圍。參數名稱:索引'

奇怪的是,如果我更改任何 ComboBox 值(這也是發生綁定錯誤時),當我關閉窗口時,它也會嘗試進行無效的數據庫更改!!!

無法將值 NULL 插入列“EmpFirstName”、表“OITaskManager.dbo.Employees”; 列不允許空值。 插入失敗。 該語句已終止。

只需將樣式注釋掉,一切都完美無缺。 我該如何解決?

以防萬一有人需要它,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>

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

您收到此錯誤是因為當您驗證發現沒有問題時,Errors 集合返回時沒有任何項目,並且以下綁定邏輯失敗:

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

您正在通過特定索引訪問驗證集合。 我目前正在研究用於替換此文本的 DataTemplate 建議。

我喜歡微軟在他們的驗證模板標准示例中列出了這一點。

更新因此將上面的代碼替換為以下代碼,綁定邏輯將知道如何處理空的驗證結果集合:

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>

2019年更新

目前,要使用的正確路徑語法是:

Path=(Validation.Errors)/ErrorContent

我認為這是最好的方法:

Path=(Validation.Errors)/ErrorContent

/實際上等於 @Nathan 的CurrentItem

就我而言, CurrentItem是不行的。

嘗試將轉換器轉換為多行字符串,如here所述

就我而言,當我嘗試應用@Nation Tregillus的解決方案時遇到了這個異常:

無法在“System.Collections.ObjectModel.ReadOnlyObservableCollection”類型的數據上下文中解析屬性“CurrentItem”

所以我改用 @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"
                    >

我已經看到您在多個地方發布的代碼,但對我來說似乎很奇怪

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

不會引發任何危險信號。 但我也是 WPF 的新手,也許在每種情況下都可以使用一些秘訣。

與其嘗試使用數組索引對可能為空的集合進行索引,不如添加一個返回列表中第一個錯誤的轉換器。

CurrentItem 對我也不起作用但是@Nathtan 的回答適用於我有自定義 textBox 資源的情況。 謝謝@Nathan 我花了一個小時來解決這個問題。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM