In my WPF application I have a WebBrowser control. I have a grid containing files, and when I click on an item in the grid the file contents are retrieved from a database to be shown in the WebBrowser.
There are two types of file:
PDF: a temporary file is created, and the web broswer Navigate function is used to load the file.
HTML: The string is passed to the NavigateToString function.
If I view a PDF, then a HTML document, right clicking shows the context menu. I want to keep most things, such as print, but I want to stop the browser from letting the user go back a page, or even forwards.
Without editing the content to add Javascript etc, is there anything on the control I can do to stop the back/forward from happening?
The answer I have come up with is the Navigated event. The user control that contains the web browser has a private boolean that determines if navigation is allowed.
If it is (set through the user control's Navigate method) then the control can navigate to a new page. Once the page has loaded the boolean is set to false, meaning back / forward is disabled.
In my case this adds a bonus: Links cannot be clicked on. I don't want these loading in the browser control - I only want this to view pages selected in the grid.
However, right-click on a link still has the open in a new window option.
This may not be the best solution, but it works for me.
To disable the backspace for navigating back but still keep the link clickable and backspace function for textbox, we need to add event handler for both PreviewKeyDown and Navigating event for WebBrowser:
// member variable to indicate if the window allows navigation to other URL
private bool allowNavigation = false;
private WebBrowser bs;
// triggered every time a key is pressed down in the WebBrowser
this.bs.PreviewKeyDown += (sender, args) =>
{
if (args.Key == Key.Back)
{
// temporarily disable navigation triggered by backspace
this.allowNavigation = false;
}
};
// triggered if the WebBrowser is switching URL (either by backspace or link clicking)
this.bs.Navigating += (sender, args) =>
{
if (!allowNavigate)
{
// if not allowed, cancel navigation and set back allowNavigation
// this will only cancel the navigation triggered by backspace
args.Cancel = true;
this.allowNavigation = true;
}
};
Related
I have a C# 4.0 WinForms application, which has a WebBrowser control and 2-buttons.
Clicking the first button sends a URL to the browser to navigate to a specified webSite.
Clicking the second button parses the OuterHtml of the webBrowser1.Document, looking for an "https://..." link for File Download.
The code then uses a webClient.DownloadFileAsync to pull down a file for further use in the application.
The above code successfully works, if I manually click those buttons.
In an effort to automate this for the end-user, I place the first button's click event, i.e. btnDisplayWeb.PerformClick(); in the form's Form1_Load event. This also works, allowing the webBrowser1 to populate its Document with the desired webSite.
However, I am unable to programatically click the 2nd button to acquire the web link for file download.
I have tried to place the 2nd buttons click event within the browser's DocumentCompleted event, as shown below.
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
btnMyUrl.PerformClick();
}
However, from what I've read on StackOverFlow and other sites, it's possible that this particular event gets called more than once, and hence it fails.
I've also attempted to loop for a number of seconds, or even use a Thread.Sleep(xxxx), but the browser window fails to populate until the sleep or timer stops.
I attempted to use the suggestions found on the following StackOverFlow site shown below.
How to use WebBrowser control DocumentCompleted event in C#?
private void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
string url = e.Url.ToString();
if (!(url.StartsWith("http://") || url.StartsWith("https://")))
{
// in AJAX
}
if (e.Url.AbsolutePath != this.webBrowser.Url.AbsolutePath)
{
// IFRAME
}
else
{
// REAL DOCUMENT COMPLETE
}
}
However, in parsing the OuterHtml, nothing is returned in the first two sections, and in the third section, other elements are returned instead of the desired "https://..." link for File Download.
Interestingly, if I use a webBrowser1.ReadyState event, as shown below, and place a MessageBox inside DocumentCompleted, this seems to allow the browser document to complete, because after clicking the OK button, the parsing is successful.
if (webBrowser1.ReadyState == WebBrowserReadyState.Complete)
{
MessageBox.Show("waiting", "CHECKING");
btnMyUrl.PerformClick();
}
However, I then have the difficulty of finding a way to click the OK button of the MessageBox.
Is there another event that occurs after the DocumentCompleted event.
OR, can someone suggest how to programmatically close the MessageBox?
If this can be done in code, then I can perform the buttonClick() of the 2nd button in that section of code.
After finding that the addition of a MessageBox allows the webBrowser1.Document to complete, and using webBrowser1.ReadyState event within the webBrowser_DocumentCompleted event, all I needed to do, was to find a way to programmatically close the MessageBox.
Further searching on StackOverFlow revealed the following solution on the site below.
Close a MessageBox after several seconds
Implementing the AutoClosingMessageBox, and setting a time interval, closed the MessageBox and allowed my button click, i.e. btnMyUrl.PerformClick(); to successfully parse the OuterHtml and now the code works properly.
Hopefully, if someone else discovers that placing a MessageBox within the webBrowser_DocumentCompleted event allows the document to complete; the aforementioned AutoClosingMessageBox will assist them as well.
I'm trying to detect when the user clicks on a hyperlink in a WebView control from Windows 10. Is there any way to detect this event?
If you want to catch the click itself you'll need to do that from inside the web page's JavaScript. Depending on where the page comes from you may be able to inject JavaScript code to do so with WebView.InvokeScriptAsync
If you want to detect the navigation triggered by the click then you can handle the WebView.NavigationStarting or NavigationCompleted events.
On Windows 10 I would use the WebView.NewWindowRequested event:
private void WebView1_NewWindowRequested(WebView sender, WebViewNewWindowRequestedEventArgs args)
{
Debug.WriteLine(args.Uri);
args.Handled = true; // Prevent the browser from being launched.
}
I would like to make the wpf webbroswer control read-only in the sense that I still want to be able to give users the ability to copy texts off of textfield etc but I dont want them to be ableto click button or submit forms.
I wrapped the web browser control in a wpf user control. When I set the IsEnabled proerty to false, it works i.e the webbroswer control is disabled but the user cannot select text from the page...
You can handle the WebBrowser's Navigating event and cancel it so that the user can't navigate to another page.
void myBrowser_Navigating(object sender, NavigatingCancelEventArgs e)
{
e.Cancel = true;
}
In my Windows Phone Application when I press a button for navigating to Page1 and before it finishes loading it, I press button to navigate to Page2, my application crashes. Is it correct and what is the best practice to implement this behaviour?
Update
Generally I think, the best way for me will be to block all buttons on the screen after one of them was pressed and make them active after navigation finish, so how can I do this?
The best practice is this case is to disable the Click event after the first click.
If your button was named b and you either assigned event handler in xaml or in codebehind
like
b.Click += new RoutedEventHandler(ButtonOnClick);
void ButtonOnClick(object sender, RoutedEventArgs e)
{
b.Click -= new RoutedEventHandler(ButtonOnClick);
// Navigate away now.
}
Actually my sample will stop double click on current button only but you can disable other buttons as well.
in one of my apps, i maintain a List which i iterate and show / hide, enable / disable a required. all you do is iterate and set the correct property.
foreach(var button in myButtons)
button.IsEnabled = false;
Wrap the call to NavigationService.Navigate(Page2Uri) into Dispatcher.BeginInvoke(()=> {...} ); as follows:
Dispatcher.BeginInvoke (()=> { NavigationService.Navigate(Page2Uri) });
When the user clicks on a tab, I want to fire the radconfirm window to ask them if they want to proceed. Now, I cancel the event, fire radconfirm, and in the callback, if successful, I'm trying to explicitly postback to show the new tab. I tried doing:
//In tabSelecting event on client
e.get_tab().select(); //to select the new tab because I canceled the selection earlier on
sender._postback(e.get_tab()); //to perform the postback
The RadMultiPage gets updated to the new tab's content, but the RadTabStrip does not show me the new tab selected. I see the old tab selected with the new tab's content.
Any ideas?
Thanks.
If you get your hands on the client object of the clicked tab, you can set is as selected using the set_selected method from the client API (see here).
Because I was attaching to tabSelecting, I need to add a boolean in the component to prevent the cancelling of the event the second time, because setting the selected tab was also firing tabSelecting event. That was the fix.