4

I have a TabControl with multiple TabItems. In each TabItem there needs to be this particular UserControl. Right now I'm creating X instances of the control where X is the number of TabItems I have. So this seems like a bad way to do it. So I'm wondering is there a way to have 1 instance of a control, but multiple locations for it. I know that each control can only have one parent so it seems like the answer is no.

[TabItem1] 
[CommandLine Control]
[Content unique to TabItem1] 

[TabItem2] 
[CommandLine Control]
[Content unique to TabItem2]

Is it possible to have one instance of [CommandLine Control] but in these two locations?

patrick
  • 16,091
  • 29
  • 100
  • 164

5 Answers5

4

You can achieve this using triggers which ensure that the control is not in two places at the same time, e.g.

<TabControl>
    <TabControl.Resources>
        <!-- Define control which is to be reused in resources -->
        <TextBox x:Key="SharedTB" Text="test"/>

        <!-- This style gets the shared control only if the parent
             TabItem is selected -->            
        <Style x:Key="LoadTBStyle" TargetType="{x:Type ContentControl}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=TabItem}, Path=IsSelected}"
                                         Value="True">
                    <Setter Property="Content" Value="{StaticResource SharedTB}"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </TabControl.Resources>
    <TabItem Header="TabItem 1">
        <StackPanel>
            <TextBlock Text="Lorem Ipsum"/>
            <ContentControl Style="{StaticResource LoadTBStyle}"/>
        </StackPanel>
    </TabItem>
    <TabItem Header="TabItem 2">
        <StackPanel>
            <TextBlock Text="Dolor Sit"/>
            <ContentControl Style="{StaticResource LoadTBStyle}"/>
        </StackPanel>
    </TabItem>
</TabControl>
H.B.
  • 166,899
  • 29
  • 327
  • 400
4

If you use a data template for your control and databind the tab control to a collection then the framework will only create one instance of the control and swap out its data context as you change tab items.

You can find a more detailed discussion here: Why do tab controls reuse View instances when changing tab

Community
  • 1
  • 1
17 of 26
  • 27,121
  • 13
  • 66
  • 85
2

Is the control really more or less a shared control? I mean, if you are really wanting a control to be in more places than 1, then you would be better off hosting it outside of the TabItem so that it can be accessed from any of the tab items that need it.

From your example, it looks like you might be best off spawning the items. Personally I would have the TabControls Items property bound to a collection of ViewModels that host a TabItem. Each of those would have a runtime created instance of the UserControl (with associated ViewModel and content).

CodeWarrior
  • 7,388
  • 7
  • 51
  • 78
2

It sounds like what you are looking to do can be accomplished by using a template.

Look at this link for an example of a tabitem template: http://msdn.microsoft.com/en-us/library/ms752032.aspx

JMcCarty
  • 759
  • 5
  • 17
  • Wouldn't that still end up creating all the controls? I assume (perhaps erroneously?) the OP was concerned with the resource usage of loading that many instances of the user control. – Tim May 16 '11 at 18:20
  • @Tim I guess, you would be correct. This would still make a new instance of the control for each tab item. However I do not think this should be an issue for the OP. Memory concerns are not really an issue since the control can be unloaded when switching to a new TabItem. I agree with your answer that the OP could perhaps switch where the control is with the code-behind but that it could cause issues. The only other option I could think of would be to make the control a resource in the containing control and to reference that in each tabItem (unsure thought). – JMcCarty May 16 '11 at 18:26
  • I don't believe that you can put a control into the resources and have it loaded in multiple places. I think that gives the same error as if you try to manually add the same control to multiple parents. Could be wrong though. – Tim May 16 '11 at 18:32
0

There's no way to have a "shortcut" to it the way you describe that I'm aware of, because your user control can only have one parent.

The only thing that I can think of to do is to shift it manually (via code-behind) when the user clicks on a different tab. But the "stutter" that might cause as you shift it (while better in WPF, I'd imagine than in other frameworks) might be just as bad as whatever the resource usage problems you're seeing by having multiple instances of the user control.

I guess another thing to do would be to cache the creation of the user controls so they're only loaded if the person actually clicks on the tab.

Tim
  • 14,999
  • 1
  • 45
  • 68