TabControl data binding and FocusChanged with DataTemplate views

1,142 views
Skip to first unread message

Brian Noyes

unread,
Jul 13, 2011, 8:20:47 AM7/13/11
to wpf-di...@googlegroups.com

I dealing with a problem that I am hoping one of you has solved elegantly already and can point me to a solution.

 

I have a tab control in a parent view with a set of child views in the tabs. It is being done with MVVM, with the parent view model containing a collection of child view models which the tab control is bound to:

    class MainWindowViewModel

    {

        public MainWindowViewModel()

        {

            ChildViewModels = new ObservableCollection<ViewModelBase>

            {

                new FooViewModel(), new BarViewModel()

            };

        }

        public ObservableCollection<ViewModelBase> ChildViewModels { getset; }

    }

 

 

    <Window.DataContext>
        <my:MainWindowViewModel />
    </Window.DataContext>
    <Grid>
        <TabControl ItemsSource="{Binding ChildViewModels}"/>
    </Grid>

 

The child view models derive from the ViewModelBase class that the collection contains.

The child views are being married to their view models through implicit data templates:

 

    <Window.Resources>
        <DataTemplate DataType="{x:Type my:FooViewModel}">
            <my:FooView />
        </DataTemplate>
        <DataTemplate DataType="{x:Type my:BarViewModel}">
            <my:BarView />
        </DataTemplate>
        <Style TargetType="TabItem">
            <Setter Property="Header"
                    Value="{Binding DisplayName}" />
        </Style>
    </Window.Resources>

 

This is all pretty standard parent-child MVVM set up for dynamic sets of child views that I’m sure most of you are familiar with.

 

The challenge has to do with data bindings in the child views. If you use the default binding Mode of LostFocus, then if you have an edit in progress in a TextBox or other control and you click on a different tab, the tab control never takes the focus away from the control before it releases the instance of the view (since it constructs a new instance of the data template each time it presents a tab item). This means the edit in progress in the focused control is lost when you select another tab. This problem does not happen if you statically wire up the view and view model and add the views as the items to the tab control instead of adding the view models as the items because then there is no dynamic data template instantiation that is constructing the views on each tab item change. We need to stick to the data template approach because we are dynamically injecting the views and view models with MEF for extensibility reasons, and the parent view model has to push some data into the child view models.

 

Obviously the quick answer to this is to use UpdateSourceTrigger=PropertyChanged on the bindings. But with the validation scheme we need for some of the controls, this is undesirable because we don’t want to annoy the user with invalid input indications until they have completed their input.

 

Is there some way to force the TabControl to change focus on the child view before it switches tabs when using data templates to render the view?

Thanks

Brian

-----------------------------------------
Brian Noyes
Chief Architect, IDesign Inc
Microsoft Regional Director / MVP
http://www.idesign.net
+1 703-447-3712
-----------------------------------------

 

Jeremy Alles

unread,
Jul 13, 2011, 8:27:35 AM7/13/11
to wpf-di...@googlegroups.com
Brian,

I think I already encountered this kind of issue once. I don't have the code with me right now but I remember solving this with some hack to move the focus away from the current focused TextBox. You can try to call Keyboard.Focus(uiElement) to change the current keyboard focus. It was not very elegant but it was working !

Hope it helps,
Jeremy

Peter O'Hanlon

unread,
Jul 13, 2011, 8:29:39 AM7/13/11
to wpf-di...@googlegroups.com
It occurs to me that you could possibly use an attached behaviour on the tab control to catch the current changing event on the items. You should be able to use that to manage the focus.

From: Brian Noyes
Sent: 13 July 2011 13:20
To: wpf-di...@googlegroups.com
Subject: [WPF Disciples] TabControl data binding and FocusChanged with DataTemplate views

Brian Noyes

unread,
Jul 13, 2011, 8:30:30 AM7/13/11
to wpf-di...@googlegroups.com

Actually just did some more digging. The problem is not that it is not changing focus on the form, the problem is that it is setting the DataContext on the view to null before it changes focus, so the binding can no longer write the current value to the view model.

Sacha Barber

unread,
Jul 13, 2011, 8:55:50 AM7/13/11
to wpf-di...@googlegroups.com
We don't use the standard TabControl, its plain evil. Someone in this group created a TabControl which the VisualTree did not get ripped out on Tab change.

Can't recall think it may have been Eric?

Link anyone?
--
Sacha Barber
sacha....@gmail.com

Sacha Barber

unread,
Jul 13, 2011, 9:03:21 AM7/13/11
to wpf-di...@googlegroups.com
I used thatTabControlEx (that's what I called it) in an article : http://www.codeproject.com/KB/WPF/CinchIII.aspx#CloseVM
--
Sacha Barber
sacha....@gmail.com

Sacha Barber

unread,
Jul 13, 2011, 9:12:29 AM7/13/11
to wpf-di...@googlegroups.com
In fact here is a link that talks about your problem exactly :http://updatecontrols.codeplex.com/discussions/214434

And guess how they solved it, they used Eric TabControl (the one I use) too.

Bottom line : Standard TabControl is evil
--
Sacha Barber
sacha....@gmail.com

Peter O'Hanlon

unread,
Jul 13, 2011, 9:14:07 AM7/13/11
to wpf-di...@googlegroups.com
It was Eric who came up with it. I would suspect that you will want to read this thread as well. http://groups.google.com/group/wpf-disciples/browse_thread/thread/4352afde28001c00?pli=1

From: Sacha Barber
Sent: 13 July 2011 14:03

To: wpf-di...@googlegroups.com
Subject: Re: [WPF Disciples] TabControl data binding and FocusChanged with DataTemplate views

I used thatTabControlEx (that's what I called it) in an article : http://www.codeproject.com/KB/WPF/CinchIII.aspx#CloseVM

Brian Noyes

unread,
Jul 13, 2011, 9:16:26 AM7/13/11
to wpf-di...@googlegroups.com

Awesome, thanks. That does appear to be a straightforward solution to this problem.

You guys rock.

Brian

Sacha Barber

unread,
Jul 13, 2011, 9:20:28 AM7/13/11
to wpf-di...@googlegroups.com
Shucks man dang you welcome bro
--
Sacha Barber
sacha....@gmail.com

Eric Burke

unread,
Jul 13, 2011, 9:40:30 AM7/13/11
to wpf-di...@googlegroups.com
As I started reading Brian's post, I said, "Oh, I bet my TabControlEx would help!" and then I saw that Sacha and Peter beat me to the punch. :)

This control has come in handy, apparently.  I was teaching a WPF class at a company in NYC in 2009.  One of the students had a question about his project from work.  He showed me the code and said, "Oh, yeah, we're using some TabControlEx class that we found on the forums".  I said, "I'm familiar with it." :)

WPF 4ever even if the media doesn't think so. :)

-E


From: Peter O'Hanlon <pete.o...@gmail.com>
To: "wpf-di...@googlegroups.com" <wpf-di...@googlegroups.com>
Sent: Wednesday, July 13, 2011 9:14 AM
Subject: RE: [WPF Disciples] TabControl data binding and FocusChanged with DataTemplate views

Sacha Barber

unread,
Jul 13, 2011, 9:44:10 AM7/13/11
to wpf-di...@googlegroups.com
Yeah that TabControl is very very handy
--
Sacha Barber
sacha....@gmail.com

Brian Noyes

unread,
Jul 13, 2011, 9:58:35 AM7/13/11
to wpf-di...@googlegroups.com

So can anyone point me to a completed sample or something that shows the whole thing, not just pasted code in a forum thread? I’ve got it working, but had to find another sample that showed that I need a control template modification to the TabControl to create the PART_ItemsHolder it is referring to, but the sample I found then has a crappy appearance to the tabs with the simple control template it uses.

 

Is there a link to a ready to go TabControlEx class that is considered up to date along with whatever control template I need that doesn’t modify the appearance of the tabs at all (or at least noticeably)?

Thanks

Brian

Sacha Barber

unread,
Jul 13, 2011, 9:59:54 AM7/13/11
to wpf-di...@googlegroups.com
Give me 10 mins ill knock one up for you
--
Sacha Barber
sacha....@gmail.com

Sacha Barber

unread,
Jul 13, 2011, 10:10:30 AM7/13/11
to wpf-di...@googlegroups.com
Attached is a small demo, rename to .zip extract and enjoy


See MainWindow.xaml for the Style for the TabControlEx




--
Sacha Barber
sacha....@gmail.com
TabControlExDemo.zip.doc

Sacha Barber

unread,
Jul 13, 2011, 10:10:47 AM7/13/11
to wpf-di...@googlegroups.com
Took 11 mins, I must be slipping
--
Sacha Barber
sacha....@gmail.com

Brian Noyes

unread,
Jul 13, 2011, 10:15:23 AM7/13/11
to wpf-di...@googlegroups.com

Actually got there myself in similar time, just cracked open the default control template with Blend, found where to insert the grid in place of the content presenter, and now am up and running.

 

Thanks all again for the help on this one!

Brian

Sacha Barber

unread,
Jul 13, 2011, 10:59:07 AM7/13/11
to wpf-di...@googlegroups.com
Nay bother
--
Sacha Barber
sacha....@gmail.com

Sacha Barber

unread,
Jul 13, 2011, 10:59:38 AM7/13/11
to wpf-di...@googlegroups.com
PS : In theory my time was better as I hand coded all that, :-P
--
Sacha Barber
sacha....@gmail.com
Reply all
Reply to author
Forward
0 new messages