0

In my WPF application I have a ResourceDictionary with some Controls:

<ResourceDictionary>
    <Border x:Key="SystemBorder">
        <!-- SomeContent -->
    </Border>

    <Border x:Key="DateBorder">
        <!-- SomeContent -->
    </Border>

    <Button x:Key="QuitButton">
        <!-- SomeContent -->
    </Button>
</ResourceDictionary>

Now in my Window I have a TabControl with some TabItem, inside of every TabItem that Controls are in use.
But when I change Tabs everything is fine, but when I change back to a Tab, these Controls won't be there.

I tried to use x:Shared="False" but it made no difference.
How can I solve that problem?

Edit:
Every TabItem has the same structure:

<TabItem>
    <Grid>
        <Grid.RowDefinitions/>
            <!-- Defs -->
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions/>
            <!-- Defs -->
        </Grid.ColumnDefinitions>
    </Grid>

        <Border x:Name="Menu1" Grid.Row="0" Grid.Column="0">
            <ContentControl x:Name="Date1" Content="{DynamicResource DateBorder}">
            <!-- some Buttons -->
            <ContentControl x:Name="QuitButton1" Content="{DynamicResource QuitButton}"/>
        </Border>
        <!-- some more Borders -->
        <ContentControl x:Name="SystemBorder1" Grid.Row="3" Grid.Column="0" Content="{DynamicResource SystemBorder}"/>
</TabItem>

The DateBorder also have a Thread which updates the Date every second.

hbsrud
  • 333
  • 2
  • 12
  • so, they are there, and then they disappear? – Noctis Nov 12 '13 at 11:05
  • And how do the tabs use these resources? You should add some code. But please only the essential parts. – DHN Nov 12 '13 at 11:09
  • Well there just don't there, it's blank when I tab back. I'll edit some more Code. – hbsrud Nov 12 '13 at 11:15
  • Added some Code, and my other comment is irritating: The controls are there, but only in just one Tab, in the other Tabs there is just blank. – hbsrud Nov 12 '13 at 11:54

2 Answers2

2

If I were to wager it is probably because the borders cannot be in the visual tree multiple times.

Why don't you bind to a collection and create a DataTemplate for the tabs:

<DataTemplate x:Key="TabTemplate">
    <Grid>
        <Grid.RowDefinitions/>
            <!-- Defs -->
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions/>
            <!-- Defs -->
        </Grid.ColumnDefinitions>
    </Grid>
    <Border Grid.Row="0" Grid.Column="0">
        <!-- some Menu1-->
        <Border>
            <!-- DateBorder-->
        </Border>
        <Button>
            <!-- QuitButton -->
        </Button>
        </Border>
    </Border>
    <!-- some more Borders -->
    <Border Grid.Row="3" Grid.Column="0" >
        <!-- SomeContent -->
    </Border>
</DataTemplate>

<TabControl ItemSource="{Binding Collection}" ItemTemplate="{StaticResource TabTemplate}" />
Net Dev
  • 416
  • 4
  • 21
  • I never used DataTemplates, and well... so I didn't even had that idea to make it. The Contents of the TabItems are also individually for each Tab and I need programmatically access to the most controls inside – hbsrud Nov 12 '13 at 12:16
  • In that case perhaps you should just define those borders/Buttons in each individual tab and forgo it as a resource. Or as much as it pains me to say... Depending on your content, alter the TabItem's Template. – Net Dev Nov 12 '13 at 12:18
  • That would be the same code for over 10 times, I hoped to keep the code clearly. – hbsrud Nov 12 '13 at 12:24
  • Is it possible to break them out into usercontrols? To keep them more organized? – Net Dev Nov 12 '13 at 12:27
  • I think that would be possible for some controls, but then again I have a problem with my DateBorder, because the Thread would have to update every single one of them every second. – hbsrud Nov 12 '13 at 12:30
  • Normally I lean towards MVVM and would say bind all those tab's "DateBorder" to a single view-model property that updates with a dispatch timer or something. Again as much as it pains me to say, perhaps you could create a subclass of TabControl instead of that dateborder and have it hold the value. Then either bind to it or get it in the tabs. Though I really do recommend looking at Templating and even MVVM design it is powerful stuff. – Net Dev Nov 12 '13 at 12:34
  • Have a workaround, I'll post it later. Thanks for your ideas ;) – hbsrud Nov 12 '13 at 13:40
-1

I found a Workaround with Code behind, so I'll share it with you:

C#:

private void TabControl_SelectionChanged(sender As Object, e As SelectionChangedEventArgs)
{
    for(int i = 1; i < 4; i++)
    {
        FindName("Date" + i).Content = null;
        FindName("QuitButton" + i).Content = null;
        FindName("SystemBorder" + i).Content = null;
    }

    var tc = (TabControl) sender;
    var index = tc.SelectedIndex + 1;

    FindName("Date" + index).Content = FindResource("DateBorder");
    FindName("QuitButton" + index).Content = FindResource("QuitButton");
    FindName("SystemBorder" + index).Content = FindResource("SystemBorder");
}

VB:

Private Sub TabControl_SelectionChanged(sender As Object, e As SelectionChangedEventArgs)
    For i = 1 To 3
        FindName("Date" & i).Content = Nothing
        FindName("QuitButton" & i).Content = Nothing
        FindName("SystemBorder" & i).Content = Nothing
    Next

    Dim tc = CType(sender, TabControl)
    Dim index = tc.SelectedIndex + 1

    FindName("Date" & index).Content = FindResource("DateBorder")
    FindName("QuitButton" & index).Content = FindResource("QuitButton")
    FindName("SystemBorder" & index).Content = FindResource("SystemBorder")
End Sub
hbsrud
  • 333
  • 2
  • 12