I'm building an application using WPF. I have a HostFrame on my Main Window where I'm binding to the CurrentPage property on my ViewModel. CurrentPage is an enum containing names of all pages. I also have a converter that converts the name of the current page to the actual page. My converter takes the pages from NInject dependency container and returns the corresponding page. All of my pages are created when the application is started inside the dependency container. Now, the problem is that I'm experiencing lag and slow performances when navigating through different pages. I would like to have something like a loading screen when the app starts for the first time and preload all pages and then when all pages are preloaded remove the loading screen. I don't know how to preload the pages.
HostFrame.xaml
<UserControl x:Class="Client.HostFrame"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Client"
mc:Ignorable="d"
d:DesignHeight="562" d:DesignWidth="800">
<Grid>
<Frame Grid.Row="1" NavigationUIVisibility="Hidden" x:Name="OldPage"></Frame>
<Frame Grid.Row="1" NavigationUIVisibility="Hidden" x:Name="NewPage"></Frame>
</Grid>
</UserControl>
HostFrame.xaml.cs
namespace Client
{
/// <summary>
/// Interaction logic for HostFrame.xaml
/// </summary>
public partial class HostFrame : UserControl
{
public BasePage CurrentPage
{
get { return (BasePage)GetValue(CurrentPageProperty); }
set { SetValue(CurrentPageProperty, value); }
}
// Using a DependencyProperty as the backing store for MyProperty. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CurrentPageProperty =
DependencyProperty.Register(nameof(CurrentPage), typeof(BasePage), typeof(HostFrame), new UIPropertyMetadata(CurrentPagePropertyChanged));
private static void CurrentPagePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// Get the frames
var newPageFrame = (d as HostFrame).NewPage;
var oldPageFrame = (d as HostFrame).OldPage;
// Store the current page content as the old page
var oldPageContent = newPageFrame.Content;
// Remove current page from new page frame
newPageFrame.Content = null;
// Move the previous page into the old page frame
oldPageFrame.Content = oldPageContent;
// Animate out previous page when the Loaded event fires
// right after this call due to moving frames
if (oldPageContent is BasePage oldPage)
oldPage.ShouldAnimateOut = true;
// Set the new page content
newPageFrame.Content = e.NewValue;
}
public void NavigateToPage(Page newPage)
{
// Set the content of the NewPage frame to the specified page
NewPage.Content = newPage;
}
public HostFrame()
{
InitializeComponent();
}
}
}
Dependency Container
public class IocContainer
{
public static IKernel Kernel { get; private set; } = new StandardKernel();
public static void Setup()
{
BindViewModels();
}
private static void BindViewModels()
{
Kernel.Bind<ApplicationViewModel>().ToConstant(new ApplicationViewModel());
Kernel.Bind<MainViewModel>().ToConstant(new MainViewModel());
Kernel.Bind<LoginViewModel>().ToConstant(new LoginViewModel());
Kernel.Bind<LoginView>().ToSelf().InTransientScope();
Kernel.Bind<SideMenuViewModel>().ToConstant(new SideMenuViewModel());
Kernel.Bind<SideMenuUserControl>().ToConstant(new SideMenuUserControl());
Kernel.Bind<DashboardViewModel>().ToConstant(new DashboardViewModel());
Kernel.Bind<Dashboard>().ToConstant(new Dashboard());
Kernel.Bind<MembersViewModel>().ToConstant(new MembersViewModel());
Kernel.Bind<Members>().ToConstant(new Members());
Kernel.Bind<RegistrationViewModel>().ToConstant(new RegistrationViewModel());
Kernel.Bind<Registration>().ToConstant(new Registration());
Kernel.Bind<InventoryViewModel>().ToConstant(new InventoryViewModel());
Kernel.Bind<Inventory>().ToConstant(new Inventory());
Kernel.Bind<CalendarViewModel>().ToConstant(new CalendarViewModel());
Kernel.Bind<Calendar>().ToConstant(new Calendar());
Kernel.Bind<ShopViewModel>().ToConstant(new ShopViewModel());
Kernel.Bind<Shop>().ToConstant(new Shop());
Kernel.Bind<HomeViewModel>().ToConstant(new HomeViewModel());
Kernel.Bind<HomeView>().ToConstant(new HomeView());
// Popups
Kernel.Bind<AddNewItem>().ToConstant(new AddNewItem());
Kernel.Bind<Overlay>().ToConstant(new Overlay());
}
public static T Get<T>()
{
return Kernel.Get<T>();
}
}
Page converter
public class ApplicationPageValueConverter : BaseValueConverter<ApplicationPageValueConverter>
{
public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
switch ((ApplicationPage)value)
{
case ApplicationPage.Home:
return IocContainer.Get<HomeView>();
case ApplicationPage.Dashboard:
return IocContainer.Get<Dashboard>();
case ApplicationPage.Members:
return IocContainer.Get<Members>();
case ApplicationPage.Register:
return IocContainer.Get<Registration>();
case ApplicationPage.Calendar:
return IocContainer.Get<Calendar>();
case ApplicationPage.Inventory:
return IocContainer.Get<Inventory>();
case ApplicationPage.Shop:
return IocContainer.Get<Shop>();
case ApplicationPage.Login:
return IocContainer.Get<LoginView>();
default:
Debugger.Break();
return null;
}
}
public override object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
MainWindow
<local:HostFrame Grid.Row="1" Grid.Column="1" x:Name="MainFrame" Panel.ZIndex="1"
DataContext="{Binding ApplicationViewModel.CurrentPage,
Converter={local:ApplicationPageValueConverter},
UpdateSourceTrigger=PropertyChanged}" Grid.RowSpan="2"
CurrentPage ="{Binding}">
</local:HostFrame>