0

I'm using Caliburn.Micro as a MVVM framework and I have an app that has a TabControl and each Tab is a ViewModel (and View) that has a couple of buttons on it and a custom UserControl I built, that also has a button in it. All of the tabs have the same structure (they use the same ViewModel/View).

The problem is that, for some reason, when I click the button inside the custom UserControl, that resets other Tabs - the controls inside reset to their initial values, DataGrids get cleared etc. The weird thing about this is that:

it doesn't happen always, it doesn't always happen to all tabs AND it happens even if I comment out everything within the UserControl's button's Click event (so just by the Click event being raised, some and sometimes all tabs just reset for no reason).

I've read that TabControl has this weird thing where it doesn't persist data in some cases, but

a) I don't think this is the case, because the data persists fine when switching between tabs, it just disappears when I click the button

b) Even if it is the same issue, I can't really use the solutions provided by Google, because the binding of Views, ViewModels and the TabControl is done by Caliburn.Micro and I can't mess around with how it does that (so, for example, I can't make the TabControl use a new property instead of ItemSource as some posts suggest).

It looks like it just completely resets the whole view just as if the app was just launched. When I read about the persistence issues of TabControl, people usually meant that things like sorting settings, selections get cleared, but in this case the whole tab clears including the data of DataGrids and everything else. I noticed that it only re-creates the views (their constructors get called when switching back to their tabs), but the ViewModels behind the views don't!

Has anyone else experienced this before? What did you do?

Fabis
  • 1,932
  • 2
  • 20
  • 37

2 Answers2

0

I had been searching for hours and somehow completely missed this solution: Stop TabControl from recreating its children

I'm not really sure how it works, but it somehow stops the Views from getting re-created when switching tabs and pressing any buttons.

Community
  • 1
  • 1
Fabis
  • 1,932
  • 2
  • 20
  • 37
  • Not idea how this one works either. I was thinking that maybe theres a way to create a TabItem from c# code and assign The SelectedItem on enter or exit of the tab, to make sure the tabitem is persistant and not Deposed of between tab selections. – Bimo Sep 27 '17 at 15:32
0

One Solution maybe to avoid using TabItems to hold your controls. Instead leave the TabItems empty, and add all of the controls that normally would go in a TabItems into the same grid element and set the Panel.ZIndex higher for the control that you want on top. Example:

<Window x:Class="testtab.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="testtab" Height="300" Width="300"
    >

    <Grid Name="Grid1">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>          
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>     
        </Grid.RowDefinitions>

        <Label Grid.Row="0" Content="Persistant State for UserControls" 
               Background="Blue" Foreground="Yellow"/>

        <TabControl Grid.Row="1" 
               Name="TabControl1"
               SelectionChanged="TabControl_SelectionChanged">
            <TabItem Header="Page1" />
            <TabItem Header="Page2" />
            <TabItem Header="Page3" />
        </TabControl>

        <!-- ZIndex: top=1; botton=0 -->
        <TextBox Name="b1" Grid.Row="2" Panel.ZIndex="1" Text="b1"/>
        <TextBox Name="b2" Grid.Row="2" Panel.ZIndex="0" Text="b2"/>
       <TextBox Name="b3" Grid.Row="2" Panel.ZIndex="0" Text="b3"/>     
    </Grid>

</Window>

Here's the related event handler:

void TabControl_SelectionChanged(
   object sender, 
   SelectionChangedEventArgs e)
{

    //need this if settings SelectedIndex on TabControl
    if (!IsInitialized) return; 

    switch(TabControl1.SelectedIndex) {
        case 0:
            Panel.SetZIndex(b1, 1);
            Panel.SetZIndex(b2, 0);
            Panel.SetZIndex(b3, 0);                             
            break;                  
        case 1:
            Panel.SetZIndex(b1, 0);
            Panel.SetZIndex(b2, 1);
            Panel.SetZIndex(b3, 0);                                                 
            break;
        case 2:
            Panel.SetZIndex(b1, 0);
            Panel.SetZIndex(b2, 0);
            Panel.SetZIndex(b3, 1);                                                 
            break;
    }
    e.Handled = true;
}

I don't have any UserControls handy... so We are using TextBox controls...

One Afterthought, You might need too also control the Visibility property for each control selecting between "Collapsed" and "Visible". In other words, if the control is not shown because its tab is not selected, then its Visibility should be set to collapsed or hidden so as not to interfere with the tab that is on top.

Bimo
  • 5,987
  • 2
  • 39
  • 61