0

I am making a WPF application with a sidebar for navigating through different pages which are loaded onto a frame. As any other sidebar, the clicked sidebar radiobutton is highlighted when clicked.

enter image description here

Now, the problem I am facing is that the pages I need to navigate to are rather heavy, with about 20+ checkboxes, 20+ textboxes, 20+ labels, and some more controls. So on the click of the radiobutton on the sidebar, there is a considerable delay till the page being navigated and thus the radiobutton being highlighted. I managed to show a loading window everytime the frame is navigating, however I can't think of a way to remove the delay between the radiobutton being clicked and being highlighted.

This question would've been helpful to me however there is a difference. I am using the style to highlight the radiobutton right away using a trigger. The style of my radiobutton is as below:

    <Style x:Key="MenuRadioButtonStyle" TargetType="{x:Type RadioButton}">
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="Foreground" Value="{DynamicResource PrimaryGrayColor}"/>
        <Setter Property="Cursor" Value="Hand"/>
        <Setter Property="FontWeight" Value="Normal"/>
        <Setter Property="FontSize" Value="15"/>
        <Setter Property="Height" Value="40"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type RadioButton}">
                    <Border x:Name="menuButton"  Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="45"/>
                                <ColumnDefinition/>
                            </Grid.ColumnDefinitions>

                            <!-- Selected  -->
                            <Border x:Name="btnSelected" Grid.ColumnSpan="2"  CornerRadius="4" Width="210" HorizontalAlignment="Right"/>

                            <!-- Indicator -->
                            <Rectangle x:Name="Indicator" HorizontalAlignment="Left" Width="4" Height="40" VerticalAlignment="Center" RadiusX="2" RadiusY="2"/>

                            <!-- Icon -->
                            <Path x:Name="Icon" Data="{Binding Tag, RelativeSource={RelativeSource AncestorType={x:Type RadioButton}}}" Height="24" Width="24" Stretch="None" Fill="{DynamicResource PrimaryGrayColor}" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0 0 5 0"/>

                            <!-- Text -->
                            <TextBlock x:Name="txtName" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="12 0 0 0"
                                                Grid.Column="1" Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}"
                                                FontWeight="{TemplateBinding FontWeight}"
                                                FontSize="{TemplateBinding FontSize}"/>
                        </Grid>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="txtName" Property="Foreground" Value="{DynamicResource PrimaryBlueColor}"/>
                            <Setter TargetName="Icon" Property="Fill" Value="{DynamicResource PrimaryBlueColor}"/>
                            <!-- Optional 
                            <Setter TargetName="Indicator" Property="Fill" Value="red"/>
                            <Setter TargetName="Indicator" Property="Height" Value="20"/>-->
                        </Trigger>
                        <Trigger Property="IsChecked" Value="True">
                            <Setter TargetName="Icon" Property="Fill" Value="{DynamicResource PrimaryBlueColor}"/>
                            <Setter TargetName="Indicator" Property="Fill" Value="{DynamicResource PrimaryBlueColor}"/>
                            <Setter TargetName="Indicator" Property="Height" Value="20"/>
                            <Setter TargetName="btnSelected" Property="Background" Value="{DynamicResource SecundaryGrayColor}"/>
                            <Setter TargetName="txtName" Property="Foreground" Value="{DynamicResource PrimaryBlueColor}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Thanks in advance.

Edit: The page looks like this, no data loading enter image description here

TheCoder
  • 303
  • 2
  • 9
  • Can I ask where this loading time comes from? I mean this is related to the load of some datas ? – Stefano Cavion Oct 29 '21 at 07:35
  • No loading of data, just a lots of textboxes and fields. I'll add a screenshot of the page to my question right away. – TheCoder Oct 29 '21 at 07:37
  • I would think about splitting navigation into two steps: one, change the route, clear the main view, select radio button, then trigger loading the page another command – Krzysztof Skowronek Oct 29 '21 at 07:38
  • 1
    So I presume you are creating a brand new control on each click on the sidebar. There is a reason for not creating all the control at the startup and than just update the datas of them when showing ? – Stefano Cavion Oct 29 '21 at 07:40
  • 1
    @StefanoCavion I navigate using this line of code `PagesNavigation.Navigate(new MyPage());`. So should I try declaring a MyPage on startup like `MyPage mypage = new MyPage();` and then using it as `PagesNavigation.Navigate(mypage());`? – TheCoder Oct 29 '21 at 07:44
  • @KrzysztofSkowronek Didn't quite get it, could you please elaborate? – TheCoder Oct 29 '21 at 07:45
  • @TheCoder yes something like that but the correct syntax should be this `PagesNavigation.Navigate(mypage);` – Stefano Cavion Oct 29 '21 at 07:48
  • Have you considered using Prism? You can load views once and use like a shared object. Handle changes in viewmodel. During heavy navigation, you show loading indicator. – Ugur Oct 29 '21 at 08:23
  • that's quite complicated, but can help with navigation performance. You need a queue of commands and worker in seperate thread that does the work. You issue a command: navigate to page x, which select the radio button and displays a spinner, then issues another command, load page x in main view (you to work with schedulers and dispatchers here). I don't know of any ready made solutions for that - I had to make it form scratch for my app – Krzysztof Skowronek Oct 29 '21 at 09:11
  • @StefanoCavion That was it! I don't know how I didn't think of it before. Preloading the pages reduced the delay considerably. If you could add that as the answer i'll accept it. I'm thinking of shifting from using the controltemplate triggers so I can control the sequence of events. – TheCoder Oct 29 '21 at 10:21
  • @TheCoder I've made it as answer ;) – Stefano Cavion Oct 29 '21 at 10:34

1 Answers1

0

The problem is that you are not preloading your pages you can switch easily form this

PagesNavigation.Navigate(new MyPage());

to this

MyPage mypage = new MyPage(); // Place this line in your init method  


PagesNavigation.Navigate(mypage); // Replace the previous navigate with this line

In this way all your load time will be at the start of the application (or where you place the initialization) and also you doesn't recreate several time the same page.

Stefano Cavion
  • 641
  • 8
  • 16