I have a Page (showDocuments) that shows documents and folders (like in Dropbox or Google Drive). When a user clicks on a folder I'm trying to navigate to a new instance of the showDocuments Page in order to show the content of the clicked folder. However, when I render the new information, it appears both the new documents and the previous ones.
I could do it by just having one page and cleaning it each time, but I need different pages in order to go back to the parent folders using frame.GoBack(), since it is much faster rather than using frame.Navigate(...) and compute and print everything again.
I'm not using a MVVM model, I just have a page and I decide which objects I need to show on the xaml.cs file.
Should I use views instead of pages?
Thanks for your time.
Try by handle the back button operation to catch parameters and navigating back.
You could have global vars of parent folder: the value (parentFolderVar) you pass to showDocuments Page and isReturn that is setted in OnNavigatedTo Method:
App.parentFolderVar = someValue;
So, when you handle tha back operation in App.xaml.cs:
private void OnBackRequested(object sender, BackRequestedEventArgs e)
{
if (rootFrame.SourcePageType == typeof(showDocuments))
App.isReturn = true;
e.Handled = true;
Pause();
}
And in showDocuments navigation:
protected override void OnNavigatedTo(object sender, NavigationEventArgs e)
{
if(App.isReturn)
//You know the parent folder with App.parentFolderVar
//Make operations
App.parentFolderVar = updatedParentFolderValue;
App.isReturn = false;
}
Related
I'm trying to create a simple application with two pages.
Using one window, I created a frame called frameHolder and within it, I want to open two pages, one is the MainMenuPage and the other is the PicturesPage. I can use frameHolder.Navigate(MainMenuPage) and frameHolder.Navigate(PicturesPage), but every time I click on the button of one of the pages, it creates another instead of going to the one which was already created.
In a simple application like mine there's no problem, but in a big application where you need to save memory it would. How can I verify if a page is open using Frame? If it's not I want to open, if it's open I want to go there.
---- I solved it, for the moment -----
As I said, it's a simple program that only have two pages. It makes it easy to fix using Frame.CanGoBack() and Frame.CanGoForward().
private void goMainMenu(object sender, MouseButtonEventArgs e)
{
if (frameHolder.CanGoBack == true)
{
frameHolder.GoBack();
}
else
{
frameHolder.Navigate(mainPage);
}
}
private void goPicturesPage(object sender, MouseButtonEventArgs e)
{
if (frameHolder.CanGoForward == true)
{
frameHolder.GoForward();
}
else
{
frameHolder.Navigate(picPage);
}
}
I'm basically telling the program that if I can go forward, then do it. If not, create a picPage, for example.
Not sure how I would do it if I had more than two pages though.
I am using a <Frame ..../> in the MainWindow.xaml to switch between two pages. The problem is that, when I return to a page all data (like textBox.Text and so on) are erased. How can I switch between the pages and keep their information all?
Loading a page is done by ClickHandler of a button in the MainWindow.xaml.cs. below is the code of ClickHandler.
private void ClickHandlerButton1(object sender, RoutedEventArgs e)
{
mainFrame.Content = new page1();
}
private void ClickHandlerButton2(object sender, RoutedEventArgs e)
{
mainFrame.Content = new page2();
}
I believe, once I click the button it creates a new page(), so I actually don't return to the same page() but go to a new page(). Therefore, there are no data to show back. However, I don't know how to get rid of this issue.
Thank you in advance.
You just use cache.
Example.
Page page1 = new Page();
Page page2 = new Page();
private void ClickHandlerButton1(object sender, RoutedEventArgs e)
{
mainFrame.Content = page1;
}
private void ClickHandlerButton2(object sender, RoutedEventArgs e)
{
mainFrame.Content = page2;
}
You are instantiating a new page and storing its reference in the Content property that was referencing the previous page.
There are multiple ways to achieve what you need:
One would be to share the viewmodel (the page where the mainFrame is has a viewmodel shared with page 1 and page 2).
Other way would be to (depending on how is your layout) to use navigation pages, carouselviews or another control that behaves like you expect. This way you keep alive the references of the views.
The third one is what Taehyung Kim said. Another way to keep the references alive is to have 2 variables. Every variable referencing an instance, in your case, page1 and page2. Then everytime that the page has to be loaded, you don't create a new instance, instead, you reuse the stored reference.
Fourth would be using datacontext of the page (for the bindings).
Fifth would be passing data at the constructor of the page (it is less performant than the second way).
Here is a link to microsoft docs that has some parts on passing data between navigations hierarchical navigation
I am trying to prevent the back button being used by expiring the pages.
I have been trying to find an article on here to help and nothing works.
I have the function below that I call as the first thing on all my pages.
I call it in the Page_Load handler, is that the right place ?
I see no errors which is good, but my application just reacts as if there is no change. The back/forward buttons work and the pages display as normal and don't expire.
UPDATE:
As an added layer of security, what I want is the page to time out so if they use the "back" button they won't get the previous page. I have F5 covered so that doesn't repeat posts, and login is covered, if as I abandon the Session when they log out. But I want to stop the back button showing the previous page and force them to use the app navigation to get around my application.
I've known this functionality to fail penetration testing so I want to cover that off before I get to that point.
J
protected void Page_Load(object sender, EventArgs e)
{
MyWebApplication.SetPageStatus(Response);
....
}
internal static void SetPageStatus(System.Web.HttpResponse oResponse)
{
oResponse.ClearHeaders();
oResponse.ExpiresAbsolute = DateTime.Now;
oResponse.Expires = 0;
oResponse.CacheControl = "no-cache";
oResponse.Buffer = true;
oResponse.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);
oResponse.Cache.SetExpires(DateTime.UtcNow);
oResponse.Cache.SetNoStore();
oResponse.Cache.SetRevalidation(System.Web.HttpCacheRevalidation.AllCaches);
}
I am working on a Windows Phone application, here is the scenario that I have problem:
So I have three pages, lets call it page 1, 2, 3.
In page 1, I have a button called start downloading. Click the button and use NavigateService.Navigate(page2Uri) and navigate to page2.
Page 2 makes query and downloads images from internet, so in its OnNavigateTo handler, I check the page back stack, if it is navigated from page 1, I will do the download. In the app bar of this page, I have a button that can navigate to page3.
Page 3 is a list of options that will perform some behavior on the image that is downloaded in page2. Once I choose an option, I want to go back to page 2 and perform some behavior on the loaded image.Here the question comes: if I use NavigateService.Navigate(page2Uri) to navigate from page3 to page2, it will call the Page2 constructor and OnNavigateTo handler again, which will cause it to lose every instance variable it already got.
But if I use NavigatService.GoBack it will go back to page2, then realizes that the backstack top entry is page1 (since page1 -> page2 -> page3). So it will re-download everything again.
I dont want anything to be downloaded again when navigate back form page3 to page2. So wondering if anyone has good idea about this.
Thank you.
You can use the query parameters and NavigationEventArgs to help.
First, you can use the NavigationEventArgs to determine if the user is going forward or background by checking the NavigationMode.
Second, you can tell page 2 to download by using the query parameters.
From page1:
private void MoveToPage2FromPage1()
{
NavigationService.Navigate(new Uri("/Page2.xaml?shouldDownload=true", UriKind.Relative));
}
and page2:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (e.NavigationMode == NavigationMode.Back) return;
string shouldDownload = ""; //May not be needed if you'll only ever go to page 2 from page 1 to download...
if (NavigationContext.QueryString.TryGetValue("shouldDownload", out shouldDownload))
{
Convert.ToBoolean(shouldDownload);
}
}
There are several ways to pass data to another page:
You can use query parameters as Shawn suggested.
You can use global data stored somewhere like in app.cs
You can use a static class to hold the data.
You can use a shared viewModel to hold the parameters. (or static properties in the viewmodel)
It all depends on the particular case. I think Shawns suggestion of using query paramaters is probably the most 'correct' MVVM way, but the other methods have their place.
You need to implement the following function and the navigation service.
These code will definitely solve your problem
for two or more parameters, use this code
String download="true";
String file="image";
NavigationService.Navigate(new Uri("/Page3.xaml?download="+download+"&file="+file+"", UriKind.Relative));
OnNavigatedTo, add the following code on to your Page2
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
String download=NavigationContext.QueryString["download"];
String file=NavigationContext.QueryString["file"];
}
For the above OnNavigatedTo function outputs true and image. You can use MessageBox.Show(); to output
I am working on a web crawler. I am using the Webbrowser control for this purpose. I have got the list of urls stored in database and I want to traverse all those URLs one by one and parse the HTML.
I used the following logic
foreach (string href in hrefs)
{
webBrowser1.Url = new Uri(href);
webBrowser1.Navigate(href);
}
I want to do some work in the "webBrowser1_DocumentCompleted" event once the page is loaded completely. But the "webBrowser1_DocumentCompleted" does not get the control as I am using the loop here. It only get the control when the last url in "hrefs" is navigated and the control exits the loop.
Whats the best way to handle such problem?
Store the list somewhere in your state, as well as the index of where you've got to. Then in the DocumentCompleted event, parse the HTML and then navigate to the next page.
(Personally I wouldn't use the WebBrowser control for web crawling... I know it means it'll handle the JavaScript for you, but it'll be a lot harder to parallelize nicely than using multiple WebRequest or WebClient objects.)
First of all, you are setting new url to same web browser control, even before it has loaded anything, this way you will simply see the last url on your browser. Definately browser will certainly take some time to load url, so I guess navigation is cancelled well in advance before Document_Completed can be fired.
There is only one way to do this simultaneously,
You have to use a tab control, and open a new tab item for every url and each tab item will have its own web browser control and you can set its url.
foreach(string href in hrefs){
TabItem item = new TabItem();
WebBrowser wb = new WebBrowser();
wb.DocumentCompleted += wb_DocumentCompleted;
wb.Url = href;
item.Child = web;
tabControl1.Items.Add(item);
}
private void wb_DocumentCompleted(object sender, EventArgs e){
/// do your stuff...
}
In order to improve above method, you should see how can you create multiple tab items in different UI threads, its pretty log topic to discuss here, but it is still possible.
Another method is to do use a queue...
private static Queue<string> queue = new ...
foreach(string href in hrefs){
queue.Enqueue(href);
}
private void webBrowser1_DocumentCompleted(object sender, EventArgs e){
if(queue.Count>0){
webBrowser1.Url = queue.Dequeue();
}
}