How can I preload a page I want to navigate to? - c#

I am building an app for WP8, and the MainPage.xaml takes a couple of seconds to load.
I want to add an animated Splash Screen, so here's what I did:
I created a new, and set it as the default navigation page
I put a StoryBoard animation in the page, with nothing else around, so that it loads fast
Now if I try to navigate to the main page from this page, it takes a couple of seconds becouse it has to load all the content as always.
A user here on stackoverflow wrote a sample of code to do something like this, saying that if you create a new instance of the page before navigating to it, it will cause the page to actually preload, making the navigation really fast.
Here's his code:
private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
{
var sb = new Storyboard();
// create your animation here
sb.Completed += (sender, args) => PreLoad();
sb.Begin();
}
private void PreLoad()
{
// this is the part that actually takes time and causes things to get loaded
// you may need it in a try/catch block depending on what is in your constructor
var page = new PageToNavigateTo();
// now create an animation at the end of which we navigate away
var sbOut = new Storyboard();
// create your animation here
sbOut.Completed += (sender, args) => NavigateToNextScreen();
sbOut.Begin();
}
private void NavigateToNextScreen()
{
// navigate here
}
protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
// remove the loading screen from the backstack so the user doesn't see it again when hitting the back button
NavigationService.RemoveBackEntry();
}
I just don't understand what he means with the line:
var page = new PageToNavigateTo();
What am I supposed to do there? I mean, which method do I have to call to create a new instance of the page I want to navigate to?
Also, inside the NavigateToNextScreen() method, do I have to use the usual
NavigationService.Navigate(new Uri("/CreditiInfo.xaml", UriKind.Relative));
or something else?
Could you help me completing this code? :)
Thank you!
Sergio

I would suggest that 'PageToNavigateTo()' should be the page constructor for the name of your next page. So in your case you would have:
var page = new MainPage();
For the navigation. That is the only way, that I know of navigating between pages on a Windows Phone 8 application.

Related

UWP Custom Constructor when creating a secondary window

I'm developing a quick application with the sole purpose of using picture-in-picture mode (compact view) in UWP to display Youtube videos over top of my work. Here's the way the current system works:
MainPage - Handles searching of youtube videos
YoutubeItem - A usercontrol that the mainpage creates for each youtube result. Approximately 50 of these are put into a wrap panel.
YoutubeViewer - A seperate page that runs in it's own window and displays the youtube video.
Here's my issue. I store all the information for the youtube video in each of the YoutubeItems. Using a button, I record the click event and handle it. Here's the code for handling the click:
private async void Button_Click(object sender, RoutedEventArgs e)
{
CoreApplicationView newView = CoreApplication.CreateNewView();
int newViewId = 0;
await newView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
Frame frame = new Frame();
frame.Navigate(typeof(YoutubeViewer), null);
Window.Current.Content = frame;
// You have to activate the window in order to show it later.
Window.Current.Activate();
newViewId = ApplicationView.GetForCurrentView().Id;
});
bool viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(newViewId);
}
The problem arises when I have to send the link for the video to the YoutubeViewer. Originally, I was doing this through a constructor but upon using this method for the Windows Documentation, I am unable to use my own constructor from my knowledge. How would you folks recommend getting the link to the new window?
There are many ways.
the simplest, though not necessarily the most elegant, is to create a new class that inherits from Frameand add to it a property for the link. Something like this:
public class FooFrame: Frame
{
public string Link;
}
then in your code assign it upon initializing the frame:
FooFrame frame = new FooFrame(){Link = "youtube.link.com"}

CefSharp documentcompleted

I am trying to use cefshar browser in C# winforms and need to know how I know when page completely loaded and how I can get browser document and get html elements,
I just Initialize the browser and don't know what I should do next:
public Form1()
{
InitializeComponent();
Cef.Initialize(new CefSettings());
browser = new ChromiumWebBrowser("http://google.com");
BrowserContainer.Controls.Add(browser);
browser.Dock = DockStyle.Fill;
}
CefSharp has a LoadingStateChanged event with LoadingStateChangedArgs.
LoadingStateChangedArgs has a property called IsLoading which indicates if the page is still loading.
You should be able to subscribe to it like this:
browser.LoadingStateChanged += OnLoadingStateChanged;
The method would look like this:
private void OnLoadingStateChanged(object sender, LoadingStateChangedEventArgs args)
{
if (!args.IsLoading)
{
// Page has finished loading, do whatever you want here
}
}
I believe you can get the page source like this:
string HTML = await browser.GetSourceAsync();
You'd probably need to get to grips with something like HtmlAgility to parse it, I'm not going to cover that as it's off topic.
I ended up using:
using CefSharp;
wbAuthorization.AddressChanged += OnAddressChanged;
and
private void OnAddressChanged(
object s,
AddressChangedEventArgs e)
{
if (e.Address.StartsWith(EndUri))
{
ResultUri = new Uri(e.Address);
this.DialogResult = DialogResult.OK;
}
}
EndUri is the final page I want to examine and ResultUri contains a string I want to extract later. Just some example code from a larger class.

CefSharp WPF web browser is not displayed Or rendered

Am new to CefSharp
I have created a class library project and referenced the CefSharp library to render the Web browser, However I am facing some issues showing the web Browser. Please find the exact code
WebBrowser_test1:
public partial class ChildWidget : Window
{
public CefSharp.Wpf.ChromiumWebBrowser webView;
public Widget()
{
InitializeComponent();
CefSharp.CefSettings settings = new CefSharp.CefSettings();
settings.PackLoadingDisabled = true;
if (CefSharp.Cef.Initialize(settings))
{
webView = new CefSharp.Wpf.ChromiumWebBrowser();
main_grid.Children.Add(webView);
webView.Address = "http://www.google.co.uk";
}
}
}
and I am referencing this library (dll) in another project
public MainWindow()
{
InitializeComponent();
Button newbutton = new Button();
newbutton.Width = 50;
main_grid.Children.Add(newbutton);
newbutton.Click += ButtonClick;
}
private void ButtonClick(object sender, RoutedEventArgs e)
{
try
{
Webbrowser_test1.ChildWidget childWidget = new Widget();
childWidget.Show();
}
catch (Exception)
{
throw;
}
}
Now on the Button click I will open the (WebBrowser_test1) child widget in which I will show the web browser .. when the window opens it is showing blank.
Please let me know if I missing anything
Subscribe to IsBrowserInitializedChanged after creating a ChromiumWebBrowser. Then once the browser is initialized you can call Load and your control will be displayed.
...
_browser = new ChromiumWebBrowser();
mainGrid.Children.Add(_browser);
_browser.IsBrowserInitializedChanged += OnIsBrowserInitializedChanged;
...
void OnIsBrowserInitializedChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (_browser.IsBrowserInitialized)
{
_browser.Load("https://www.google.com/");
}
}
I can think of the first three potential issues. But it's hard to tell what the real issue is from your code alone as it strays off a bit from the official examples
Move Cef.Initialize() to your MainWindow constructor. It should only be called once to launch the CefSharp.BrowserSubprocess.exe renderer process.
See my answer to CefSharp 3 always failing Cef.Initialize() for a few things to check regarding binaries and their placement. Really, the recommended approach is to start having the WPF example in the CefSharp.MinimalExample repo running first and then adjust to your use case from there.
I'm not sure a ChromiumWebBrowser() without explicitly setting a width and height works. A 0x0 window might not receive any rendered content. I haven't tried with recent code.
Have you tried replacing
webView.Address = "http://www.google.co.uk";
with
webView.Load("http://www.google.co.uk");
Like jornh mentions, you may have to explicitly set the height and width of the ChromiumWebBrowser. If you don't know the exact size, setting HorizontalAlignment and VerticalAlignment to Stretch (to fill the parent container) will probably also work.
Have you checked if the Cef.Initialize() actually returns true? You could be missing some files, and CefSharp doesn't always give clear error messages when this is the case.

Frame.Navigate in LoadState

I'm having trouble trying to navigate automatically between pages in my Windows 8.1 app based on a little check. It just doesn't want to navigate to another page when doing this in LoadState, as if something isn't loaded yet, but it doesn't give an error either. When I insert a delay using (for example) await Task.Delay(2000) before doing Frame.Navigate, then my app will redirect without any problem.
protected async override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
{
MyData oData = await getData();
if (oData != null)
{
this.Frame.Navigate(typeof(newPage), oData);
}
else
{
// do something else
}
}
Do I have to put this code in another load- or navigated-event? Or how can I make this work?
In LoadState and SaveState you should only save and restore the page state (called when suspending and reactivating the app). Do nothing else (like navigating).
Put your logic into the OnNavigatedTo method instead...
If you want to navigate from method that called when page is loads, you should place your navigation code to OnNavigatedTo(...). But do not forget to wrap your code in Dispatcher.RunAsync(...) - Frame navigation in xaml return false
I tried calling Frame.Navigate(...) from the OnNavigatedTo method but still the navigation didn't occur.
There are other answers which say use Dispatcher.RunAsync, but that feels like it's making assumptions about the threading model of Windows Phone.
Here's what I do: attach a handler to the Loaded event of the page instead, and put my "redirect" logic in there. Loaded fires after OnNavigateTo and after NavigationHelper_LoadState, but before the page has become visible.
public LaunchPadPage() {
this.InitializeComponent();
this.navigationHelper = new NavigationHelper(this);
this.navigationHelper.LoadState += this.NavigationHelper_LoadState;
this.navigationHelper.SaveState += this.NavigationHelper_SaveState;
this.Loaded += LaunchPadPage_Loaded;
this.app = (App)App.Current;
}
private void NavigationHelper_LoadState(object sender, LoadStateEventArgs e) {
// Let's show the root zone items
// NB: In case we don't have this data yet, do nothing
if (app.Hierarchy != null)
{
DefaultViewModel["Items"] = app.Hierarchy.RootItems;
}
}
private void LaunchPadPage_Loaded(object sender, RoutedEventArgs e) {
// No data? Go to the downloads page instead.
if (app.Hierarchy == null)
{
Frame.Navigate(typeof(DownloadingPage));
}
}

Prepare data before go to the main view

When the user touch the app icon,
I want do these steps before user go to the main view
Fetch json string from URI
Use JArray.Parse to get the value
After all finish, go to the main view.
The problem is how can I prevent user to go to the main view
and put all the code
I tried to put it in Application_Launching method in the App.xaml.cs file
// Code to execute when the application is launching (eg, from Start)
// This code will not execute when the application is reactivated
private void Application_Launching(object sender, LaunchingEventArgs e)
{
// code here
}
But it doesn't prevent the program to go to the main view before the fetching finished.
And I found that actually in the MainPage.xaml, if I put this code like this
protected override void OnNavigatedTo(NavigationEventArgs e)
{
while(true) {}
// it will prevent the program to go to the main view,
// and will stick with the loading screen until this function reach its end
}
So I think, I can put the all the code here, when I finish the fetch, I will just break the while and it will go to the main view automatically.
And I try, this is the code
protected override void OnNavigatedTo(NavigationEventArgs e)
{
bool isFetchFinished = false;
ObservableCollection<PromoViewModel> Promos = new ObservableCollection<PromoViewModel>();
WebClient client = new WebClient();
client.DownloadStringCompleted += (s, evt) =>
{
if (evt.Error == null)
{
// Retrieve the JSON
string jsonString = evt.Result;
JArray promos = JArray.Parse(jsonString);
foreach (JObject promo in promos)
{
string name = promo["name"].Value<string>();
string description = promo["description"].Value<string>();
string img = promo["image"].Value<string>();
Promos.Add(new PromoViewModel() { Name = name, Description = description, Img = img });
}
isFetchFinished = true;
System.Diagnostics.Debug.WriteLine("finish fetch");
}
};
// run
client.DownloadStringAsync(new Uri("the json url"));
while(true) {
if(isFetchFinished) {
App.ViewModel.LoadData(Promos); // pass value to main view model
break; // after complete, break
}
}
}
I thought it would work, but it was not.
This is what I found,
The WebClient DownloadStringAsync won't run until the OnNavigatedTo function finished.
Because it's still waiting for the while loop to break and reach the end function.
And this
isFetchFinished = true; // will never executed
Resulting infinite loop.
I think I put the fetch code in the wrong method. Where is the right place to put all of this?
Ouch, you are doing it all wrong. First of all, you have to specify the starting page. If you want to download some data before navigating to it, you can create a special "download" page that is actually the first page navigated to when starting the application. And then, once the download is completed, you navigate to your main page. This is actually a replacement for the extended splash screen.
Also, never put while (true) in any UI code, that will simply freeze the application. Besides, if the application is frozen, you never get the chance to "unfreeze" it.

Categories