WPF验证(IDataErrorInfo)和选项卡聚焦问题

16
我有一个绑定到实现了 IDataErrorInfo 接口的对象属性的 TextBox。我设置了 Validation.ErrorTemplate,它可以正常工作。问题是,我把它们放在了一个 TabControl 上面,如果我切换到另一个选项卡,然后再回到最初的选项卡(即 TextBox 所在的选项卡),验证模板就不再显示了。看起来它已经被验证(值正确),但事实上并没有。
这是 IDataErrorInfo 对象 - 请注意,“正确”的值是一个长度为 2 的字符串:
public class Presenter : IDataErrorInfo
{
    public Presenter()
    {
        this.Property = String.Empty;
    }

    public string Property { get; set; }

    public string Error { get { return null; } }

    public string this[string columnName]
    {
        get
        {
             if (columnName == "Property")
             {
                if (this.Property.Length == 2)
                   return null;
                else
                   return "Invalid property length!";
             }
             else return null;
        }
    }
}

这是 XAML 代码:

<TabControl >
    <TabItem Header="tabItem1" Name="tabItem1" GotFocus="tabItem1_GotFocus">
        <Grid>
            <TextBox Width="100" Height="20" x:Name="txtField">
                <TextBox.Style>
                    <Style TargetType="{x:Type TextBox}">
                        <Setter Property="Validation.ErrorTemplate">
                            <Setter.Value>
                            <ControlTemplate>
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="Auto"/>
                                        <ColumnDefinition Width="16"/>
                                    </Grid.ColumnDefinitions>
                                    <AdornedElementPlaceholder Grid.Column="0"/>
                                    <Image Source="bullets16.png" Grid.Column="1" ToolTip="{Binding CurrentItem.ErrorContent, Mode=OneWay}">
                                    </Image>
                                </Grid>
                            </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </TextBox.Style>
                <TextBox.Text>
                    <Binding Path="Property" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True">
                    </Binding>
                </TextBox.Text>
            </TextBox>
        </Grid>
    </TabItem>
    <TabItem Header="tabItem2" Name="tabItem2" >
        <Grid />
    </TabItem>
</TabControl>

有什么想法,我做错了什么吗?

2个回答

32

标签项通常会与装饰者混淆(尽管我不知道为什么,但我经历过这种情况)。

我能够重现你的问题。

通过使用AdornerDecorator来包装TabItem的内容来解决它。

所以:

<TabControl >
    <TabItem Header="tabItem1" Name="tabItem1" GotFocus="tabItem1_GotFocus">

        <AdornerDecorator>

           <Grid>
           ....
           </Grid>

        </AdornerDecorator>

    </TabItem>
    ...
</TabControl>

2
这也是Expander内容的一个问题,同样的解决方案适用。 - Robert Rossney
3
不是完整的解决方案。初始验证仅适用于第一个选定的选项卡项目,当您稍后切换到它们时,其余选项卡项目不会自动验证。我发现通过在OnLoad中在代码后台中手动设置DataContext也可以解决此问题,但这很丑陋。我仍在寻找解决方案... - MoonStom
在使用.NET 4.5.2并且使用INotifyDataErrorInfo而不是IDataErrorInfo时遇到了这个问题,这个解决方案非常适合我的用例。 - blins
2
@akjoshi提供的链接已经失效。这里是它的存档:https://web.archive.org/web/20150627034202/https://karlshifflett.wordpress.com/2008/02/19/wpf-validation-errors-disappear-inside-tabcontrol-when-switching-tabitems/ - reduckted

1

我遇到了一个问题,只有第一个(聚焦的)选项卡获得了样式,并且在更改后仅该选项卡保持了样式。这是我最终采用的解决方案(不使用AdornerDecorator

<Style TargetType="{x:Type FrameworkElement}" x:Key="ValidatingControl">
<Style.Triggers>
    <MultiTrigger>
        <MultiTrigger.Conditions>
            <Condition Property="Validation.HasError" Value="True" />
            <Condition Property="IsVisible" Value="True" />
        </MultiTrigger.Conditions>
        <Setter Property="Validation.ErrorTemplate">
            <Setter.Value>
                <ControlTemplate>
                    <DockPanel LastChildFill="True">
                        <Border BorderBrush="Red" BorderThickness="1">
                            <AdornedElementPlaceholder Name="controlWithError"/>
                        </Border>
                    </DockPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="ToolTip" 
        Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors).CurrentItem.ErrorContent}" />
    </MultiTrigger>
</Style.Triggers>

根据这篇文章:http://techqa.info/programming/question/1369643/wpf-error-styles-only-being-rendered-properly-on-visible-tab-of-a-tab-control(该链接已失效)


坏链接,跳转到付费网站。 - Chris Bordeman
1
当时还没有。已编辑。 - vvucetic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接