Persisting state when using Tab Control

I have a page with a tabControl consisting of two TabItems : TabItem-1 and TabItem-2. In my TabItem-1 I have a TextBox control (MyTextBox), the content of which I'm TwoWay binding to a business entity's property. Now my textBox uses a template defined in a Style and the style also has a trigger set where if the Validation.HasErrors property is true, change the Template of the TextBox to ErrorTemplate which basically shows an error indicator next to the Textbox Control. Everything works fine so far.

Now I have editted the content of MyTextBox to have an invalid data so that the Error indicator shows up next to the control. Next if I go to TabItem-2 and then come back to TabItem-1, the content in the TextBox is the same as what it was before but the error indicator disappeared. It looks like the TextBox is using the default Template rather than the Error Template. Why is this happening the way it is? Is the engine clearing the ErrorCollection for the TextBox control? Is there a way to persist the state of the TabItem?

Thanks

[1062 byte] By [rrn] at [2008-1-4]
# 1
I imagine this problem is caused by the elements in TabItem-1 being recreated/reloaded when you return back to that tab item. The TextBox is born again, so to speak. I'm not sure what you can do about forcing the validation logic to run on the TextBox when it is loaded. You might have to explicitly update the Text binding to force the validation rules to be executed.
JoshSmith at 2007-10-3 > top of Msdn Tech,Visual Studio Orcas,Windows Presentation Foundation (WPF)...
# 2

When you switch between tabs the content of the previous tab gets disconnected from the visual tree. Once you go back to that tab content is connected again which means your styles re-apply again.

If you want to persist some properties you need to bind them to some data source. In the same way TextBox.Text is persisted you should also bind Validation.HasError property to some data source (could be a static class field for example).

AtanasKoralski-MSFT at 2007-10-3 > top of Msdn Tech,Visual Studio Orcas,Windows Presentation Foundation (WPF)...
# 3

Thank you for your answers.

This is an interesting information .. I guess I was expecting to hear an easy solution to this problem. Persisting state in ASP.Net was pretty easy .. so I expected such simplicity with WPF too . Also using tabbed pages is a very common scenario. Writing extra logic to persist state by the method you mentioned will work but what about if you have 10 textboxes each of which has an error .. does that mean I'll have to create a Validation error property for each control and bind to it? Well, I could create an object collection that will keep track of my errored controls and apply the Error template to these controls when I return to TabItem-1 but to me this could have been made easier by the framework. Do you have any plans of implementing this sort fo persistence in your future release?
rrn at 2007-10-3 > top of Msdn Tech,Visual Studio Orcas,Windows Presentation Foundation (WPF)...
# 4

Hi Atanas,

I still dont quite understand the following behavior with TabControl. I have a textBox style as follows:

Code Snippet

<Style x:Key="TextStyleInherited" TargetType="TextBox" BasedOn="{StaticResource BaseStyleInherited}">

<Setter Property="FontSize" Value="13" />

<Setter Property="FontFamily" Value="Garamond" />

<Setter Property="Width" Value="400" />

<Setter Property="Height" Value="25" />

<Setter Property="Validation.ErrorTemplate">

<Setter.Value>

<ControlTemplate>

<DockPanel LastChildFill="True">

<Grid DockPanel.Dock="Right" Margin="5,0,0,0" VerticalAlignment="Center">

<Grid.ColumnDefinitions>

<ColumnDefinition Width="20"/>

</Grid.ColumnDefinitions>

<Grid.RowDefinitions>

<RowDefinition Height="20"/>

</Grid.RowDefinitions>

<Ellipse>

<Ellipse.Fill>

<LinearGradientBrush

StartPoint="0,0"

EndPoint="1,1">

<GradientStop Color="White"

Offset="0" />

<GradientStop Color="Red"

Offset="1" />

</LinearGradientBrush>

</Ellipse.Fill>

</Ellipse>

<TextBlock Text="!" Foreground="White" FontSize="16" FontWeight="Bold" HorizontalAlignment="Center"/>

</Grid>

<AdornedElementPlaceholder/>

</DockPanel>

</ControlTemplate>

</Setter.Value>

</Setter>

</Style>

My TextBox is defined as follows in XAML and belongs to TabItem-1

Code Snippet

<TextBox Grid.Column="2" Name="TenantNameData" Style="{StaticResource TextStyleInherited}">

<TextBox.Text>

<Binding Path="Name" UpdateSourceTrigger="LostFocus" Mode="TwoWay">

<Binding.ValidationRules>

<ExceptionValidationRule />

</Binding.ValidationRules>

</Binding>

</TextBox.Text>

</TextBox>

Questions:

  • You said "When you switch between tabs the content of the previous tab gets disconnected from the visual tree. Once you go back to that tab content is connected again which means your styles re-apply again. "If this is true, going back to the scenario I explained in my first post, why is it that the Validation.ErrorTemplate (which is part on the style) not get applied when I come back to the first TabItem. I debugged my application and saw that the ErrorCollection for the textbox is not cleared and the HasError property is still true. Could you explain this behavior?

  • Another behavior I noticed is that (same scenario as explained in the first bullet point) now my textbox has the HasError property 'True' but does not have the ErrorTemplate applied because of the behavior explained above. Next I focus on this textbox, do not do anything else and then lose focus.. I expected the errorTemplate to get applied (since the UpdateSourceTrigger = LostFocus) at this point as a result have the error indicator show up next to the textbox. BUt this does not happen. Any idea why?

  • To get around all these problems, I tried to force validation from code-behind by using BindingExpression.UpdateSource() under TabItem-1's GotFocus event. Eventhough setting focus on TabItem-1 triggers the GotFocus event and executes the logic, I do not see any visual feedback such as the error indicator next to my errored textbox which tells me that infact validation did not happen. Now if I set focus on any edittable control (for example, be it a Listbox or another textbox) inside my TabItem-1, the GotFocus event gets fired, executes the logic and now I do see the error indicator next to the textbox, which tells me validation did happen. Two things that I do not understand here are

a) why does the updateSource() under GotFocus handler does not give me a visual feedback

that validation failed inspite of forcing validation

b) why does the GotFocus event gets fired when I set focus on any of the edittable controls within

the TabItem? Should it not fire just once when the TabItem-1 gets focus?

rrn at 2007-10-3 > top of Msdn Tech,Visual Studio Orcas,Windows Presentation Foundation (WPF)...
# 5

Sorry to jump in, but I've been following the thread as I've been having the same problem. Hopefully I dont confuse the issue.

rrn - I'm experiencing the same symptoms as you describe up until the last couple points.

1) In my case, creating an error, switching to tab2, returning to tab1 also does not show the errorTemplate (same as you). But focusing the textbox, then losing focus does re-apply the errorTemplate.

2) I also forced validation with an UpdateSource() and I can see that validation does occur (I have custom validation routines, and my breakpoint in the ValidationRule is clearly hit with a call to UpdateSource()). But, the problem with showing the correct errorTemplate persists.

It appears to be that the Validation.ErrorTemplate does not actually get re-applied with the rest of the Style. Is there a way to force the Style to refresh?

ErinC at 2007-10-3 > top of Msdn Tech,Visual Studio Orcas,Windows Presentation Foundation (WPF)...
# 6

ErinC wrote:

1) In my case, creating an error, switching to tab2, returning to tab1 also does not show the errorTemplate (same as you). But focusing the textbox, then losing focus does re-apply the errorTemplate.

I tried this again with a very simple page. The page has a TabControl with two TabItems and TabItem-1 has two TextBoxes. The UpdateSourceTrigger is set to 'LostFocus' on TextBox-1. Creating an error, switching to TabItem-2, returning to TabItem-1, still does not show the error template. Focussing on the TextBox-1 and then losing focus still DOES NOT show the error template.

ErinC wrote:

2) I also forced validation with an UpdateSource() and I can see that validation does occur (I have custom validation routines, and my breakpoint in the ValidationRule is clearly hit with a call to UpdateSource()). But, the problem with showing the correct errorTemplate persists.

You are right here. My break points also hits my validation routines but the right error template does not get applied.

Hopefully somebody will help us out here.

rrn at 2007-10-3 > top of Msdn Tech,Visual Studio Orcas,Windows Presentation Foundation (WPF)...
# 7

rrn,

Ok, I finally figured out why we're seeing slightly different behavior after switching tabs, losing focus. I see the situation you describe (create error, tab2, tab1, focus and lose focus --> no error shown until typing in the field). I ONLY see this behavior when I use the ExceptionValidationRule in XAML instead of using my custom validation rules. There must be slightly different logic, whether it's in my own routines, or what's happening underneath with the bindings, I'm not sure.

I know this doesn't help us solve the problem, but at least describes it a bit better.

This seems like a bug to me. There's no reason that all the rest of the Textbox style (fonts, etc) should get re-applied after switching tabs but the Validation.ErrorTemplate shouldn't.

I'm also not seeing an acceptable workaround.

Can anyone from Msft comment?

ErinC at 2007-10-3 > top of Msdn Tech,Visual Studio Orcas,Windows Presentation Foundation (WPF)...
# 8

Erin, just curious .. were you able to find a work around for this problem?

rrn at 2007-10-3 > top of Msdn Tech,Visual Studio Orcas,Windows Presentation Foundation (WPF)...
# 9
Unfortunately, no....
ErinC at 2007-10-3 > top of Msdn Tech,Visual Studio Orcas,Windows Presentation Foundation (WPF)...
# 10

I have the same problem.

It was reported at http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1344560&SiteID=1.

I have written generic document management with specific UI implementation using WPF tabs. A document has a DataTemplate which generates its UI in a tab. But when you swich from tab1 to tab2 and back to tab1, tab1 looses its state like focus etc. This is pretty anoying - even worse for a user (and her/his "cool WPF experience" ;-).

E.g. consider simple case with RichTextBox in the document DataTemplate. User edits middle of book1 in tab1, then goes to book2 and book2 in tab2 and back to book1, but now the cursor is at the beginning of book1...

It is the simple example, but you can have much more complicated document (tab content) template of course.

Well, this should be definitely fixed in WPF. What about KeepAlive or KeepState boolean property?

Marek

MarekIstvanek at 2007-10-3 > top of Msdn Tech,Visual Studio Orcas,Windows Presentation Foundation (WPF)...
# 11

After additional investigation I have found that if you have TabControl with a ContentTemplate for its tabs, the template is used only once to generate a tab content so all tabs share the same content (same visual tree) - that is why those problems arise.

I my simple example above, if book1 and book2 has the same text and you switch from tab1 to tab2 and back, focus is preserved because its the same RichTextBox and its content is not changed.

Well, can we tell TabControl to generate new UI for each tab from the DataTemplate - at least this is how it should be, because DataTemplates exist exactly for this purpose.

MarekIstvanek at 2007-10-3 > top of Msdn Tech,Visual Studio Orcas,Windows Presentation Foundation (WPF)...
# 12

Any solutions on this yet?

DavidBrenchley at 2007-10-3 > top of Msdn Tech,Visual Studio Orcas,Windows Presentation Foundation (WPF)...
# 13

I have applied this as a bug, and Microsoft was able to confirm this as a bug.

http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=295933

DavidBrenchley at 2007-10-3 > top of Msdn Tech,Visual Studio Orcas,Windows Presentation Foundation (WPF)...
# 14

Thank you Dave ... so glad to hear that Microsoft confirmed this to be a bug ... atleast the next version will work as expected.

rrn at 2007-10-3 > top of Msdn Tech,Visual Studio Orcas,Windows Presentation Foundation (WPF)...

Visual Studio Orcas

Site Classified