UI tab control visibility changes between debug and deployed version
Asked Answered
E

1

11

I have a WPF Mvvm-Light application that uses tab controls to display different views to the user.

PROBLEM:

THe problem I have is that when the program first loads the tab control displays empty. But when debugging locally this problem never occurs. This application has been in development for over a year without this issue and all of a sudden it started happening. see below image enter image description here

HACK FIX:

If the user resizes their window, the content in the tab control refreshes and appears and the problem never reoccurs while they have the application open. But this issue occurs 100% of the time on first program load and first tab load (which happens at the same time)

DETAILS:

here is how I define my views that get inserted into the tab control

 <DataTemplate DataType="{x:Type FtcViewModel:DashboardNavViewModel}">
   <FtcView:DashboardNav  />
 </DataTemplate>

and here is my tab control:

<TabControl  Grid.Column="1" Grid.Row="3" 
                     SelectedItem="{Binding CurrentViewModel}" 
                     ItemsSource="{Binding OpenViewModelCollection}" 
                     Style="{StaticResource TabControlStyle}" 
                     ItemContainerStyle="{StaticResource TabItemStyle}" >
        </TabControl>

then in my view model for the main window i assign a collection to the tab control and by default set the dashbaord as the first tab to open like this (tried to only include relevant code, obiously there is more in the viewModel file):

Public Property OpenViewModelCollection As ObservableCollection(Of ViewModelHelper)
    Get
        Return Me._OpenViewModelCollection
    End Get
    Set(value As ObservableCollection(Of ViewModelHelper))
        If _OpenViewModelCollection Is value Then
            Return
        End If
        _OpenViewModelCollection = value
        RaisePropertyChanged(OpenViewModelCollectionPropertyName)
    End Set
End Property

Public Property CurrentViewModel As ViewModelHelper
            Get
                Return Me._CurrentViewModel
            End Get
            Set(value As ViewModelHelper)
                If _CurrentViewModel Is value Then
                    Return
                End If
                ''if change of viewmodel is not from OpenTabViewModelCommandExecute method
                If FlagOpening = False AndAlso value IsNot Nothing Then

                    If _CurrentViewModel IsNot Nothing Then
                        _CurrentViewModel.HandleNavigation(True)
                    End If

                    ''Mark NavService target VM
                    _NavService.TargetViewModelKey = value.vmKey

                    ''evaluate if naviagtion has been canceled
                    If _NavService.bCanNavigate = False Then
                        _NavService.bCanNavigate = True
                        Exit Property
                    End If
                End If
                ''if navigation not canceled, finish assigning new view model
                _CurrentViewModel = value
                RaisePropertyChanged(CurrentViewModelPropertyName)
                If _CurrentViewModel IsNot Nothing Then
                    _CurrentViewModel.RefreshModel()
                End If
            End Set
        End Property
...

'' THIS CODE IS FROM THE CONSTRUCTOR OF THE VIEW MODEL CLASS
OpenViewModelCollection.Add(_Locator.DashboardHome_VM)
CurrentViewModel = OpenViewModelCollection(0)

QUESTION

can someone help me figure out why this is happening or suggest a way to refresh the UI after the first application load.

thanks in advance

UPDATE 1 - Oct 4, 2017

I have been able to reproduce this problem on my development machine. When the UI is blank you can see that the XAML diagnostics tools don't show up. THe image below shows the same app being debugged, but the one without the XAML tools box is the one with the missing ui elements.

enter image description here

The following content is not being rendered inside my custom tab control style:

<ScrollViewer VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Auto" >
    <ContentPresenter x:Name="PART_SelectedContentHost" ContentSource="SelectedContent" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</ScrollViewer>

EDIT 2 Oct 11 2017

I have set breakpoints in both the xaml and code in the ViewModel. I can confirm that the ViewModel data is correctly initialized and assigned to the observable objects. I also inserted "test" textblocks in my tabItemTemplate to confirm which part is not showing. Right now I have a terrible hack of resizing the window from code on application startup, while that works, I still would like to figure out what is going on.

Ericaericaceous answered 29/9, 2017 at 20:58 Comment(18)
I can give you only some general advice. You can debug WPF application with WPF Snoop (snoopwpf.codeplex.com). Even if the problem occurs on a client's machine on a release version. I'd also recommend removing any binding errors if you have any - you'll find them in the output window. Logging them may also help a lot (see: github.com/bblanchon/WpfBindingErrors).Supervisory
@swiszcz thanks, I have confirmed all binding errors are removed. snoop is so old that it does not work with my app. no changeEricaericaceous
I had colleagues at work, for whom WPF Snoop wasn't working, while they had almost the same hardware/software configuration. So it's not because it's old, it's something else. Still, you need to debug your release version somehow - you can use WPF Inspector (wpfinspector.codeplex.com) with a similar features, or try to run WPF Snoop from source.Supervisory
Another hint: around .NET 3.5 there was a bug in WPF, that sometimes some styles were not applied on the first usage. You can check if this is the case by simply using your ContentPresenter twice.Supervisory
So as to a question of how to refresh your UI - there should be many ways, the first one that comes to my mind (and I know that it works) is to expand your window by 1 pixel, and next shrinking by one pixel. To have this working each operation should be called with a separate Application.Dispatcher.BeginInvoke().Supervisory
Doesn't a call to InvalidateVisual() in windows constructor solve this?Brilliancy
Or another hack is forcing re-evaluation of TabControl.ItemsSource after Main Window is loaded by calling yourTabControl.InvalidateProperty(TabControl.ItemsSourceProperty) ?Brilliancy
Looks like this issue, https://mcmap.net/q/1159618/-tabcontrol-all-tabitems-collapsed-but-content-of-1st-tabitem-still-visible - I think the root cause is to do with Message Pump filters and Got and Lost focus, see this odd case here https://mcmap.net/q/901470/-bug-can-39-t-choose-dates-on-a-datepicker-that-fall-outside-a-floating-vsto-add-in/495455 (see similar WPF case).Sergent
Have you tried swapping SelectedItem="{Binding CurrentViewModel}" and ItemsSource="{Binding OpenViewModelCollection}"?Matisse
@Brilliancy I added invalidatevisual to the application window constructor with no changeEricaericaceous
@Matisse I am not sure what that would accomplish? One is the specific item and the other is a collection of items. Why would I assign a collection to the selected item?Ericaericaceous
I think @Matisse meant switching the order in which these two properties are assigned in your XAML, albeit I don't think that will solve the problem.Rech
I supposed, that the binding of the selected item fails because it is not part of the collection. But then, the GUI would not updated after resizing - so just ignore the comment.Matisse
Any chance of providing an MCVE?Rech
Where and when do you construct and set your DashboardNavViewModel?Jubilation
@Grx70, unfortunately no, I'm just not in a situation where I could strip the app down enough to create a MCVE for others to review.Ericaericaceous
Did you manage to run any debugging tool, to see the state of the visual tree, when the view is not displayed?Supervisory
@swiszcz I have not, unfortunately I have not been able to put time into this over the last couple days, I plan on doing this early next week. I will post backEricaericaceous
O
2

This is quite hacky but you could try something like this:

Public Sub YourFormName.OnLoad ()
    Dim CorrectFormSize As Intager = YourFormName.Size
    YourFormName.Size = New Size(300, 300)
    System.Threading.Thread.Sleep(1000)
    YourFormName.Size = New Size(CorrectFormSize)
End Sub

Bear in mind that this will just automate the resize process that you described.

If you want to save a few lines because you application is going to be full screen once loaded then you can skip a few lines and do this instead:

Public Sub YourFormName.OnLoad()
    YourFormName.Size = New Size(300, 300)
    System.Threading.Thread.Sleep(1000)
    YourFormName.WindowState = System.Windows.Forms.FormWindowState.Maximized
End Sub
Oppression answered 6/12, 2017 at 22:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.