Issue with WPF validation(IDataErrorInfo) and tab focusing
Asked Answered
L

2

16

I have a TextBox bound to a property of an object which implements IDataErrorInfo. I set up the Validation.ErrorTemplate of the TextBox, and it works fine. The problem is that I have these on a TabControl, and the validation template doesn't display any more if I change the tab to another one and then come back to the initial tab (where the TextBox is). It looks like it is validated(like the value is correct), but actually it is not.

This is the IDataErrorInfo object - note that a "correct" value is a string with a length of 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;
        }
    }
}

and this is the 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>

Any ideas on what I am doing wrong?

Luminescent answered 1/3, 2010 at 12:20 Comment(0)
H
32

Tab items tend to mess up with adorners (although I don't know why, I experienced it).

I could reproduce your problem.

Solve it by wrapping the contents of the TabItem with an AdornerDecorator.

So:

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

        <AdornerDecorator>

           <Grid>
           ....
           </Grid>

        </AdornerDecorator>

    </TabItem>
    ...
</TabControl>
Hospitium answered 1/3, 2010 at 13:27 Comment(5)
This is also a problem with the content of Expander, and the same solution applies.Pasha
A related blog post - WPF Validation Errors Disappear Inside TabControl When Switching TabItemsEmma
Not a complete solution. Initial validation only works for the first selected tab item, the rest of them won't validate automatically when you later switch into them. I found out that by manually setting the DataContext in code behind in them at OnLoad solves this issue as well but it's ugly. I'm still searching for a solution...Scoop
Ran into this using while targeting .NET 4.5.2 and using INotifyDataErrorInfo instead of IDataErrorInfo and this solution worked great for my use case.Suckerfish
The link from @Emma is dead. Here's an archive of it: web.archive.org/web/20150627034202/https://…Sotos
P
1

I had problem with only first (focused) tab got style and only that one persisted after changing. This is solution I ended up with (without 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>

Based on this article: http://techqa.info/programming/question/1369643/wpf-error-styles-only-being-rendered-properly-on-visible-tab-of-a-tab-control (No longer exists)

Peptone answered 19/5, 2017 at 20:35 Comment(2)
Bad link, goes to a pay site.Semiautomatic
It wasn't at the time. Edited.Peptone

© 2022 - 2024 — McMap. All rights reserved.