How to make CefSharp WinForms control Scroll page to Link - c#

So here is the scenario, using CefSharp in a WinForms application.
We have two pieces of information a page url and a link url within that page.
We want to load the page - easily done, and have CefSharp show the area of the page where the link is located. That is cefsharp automatically scrolls to the right location on the page where that link is within the DOM.
What is the easiest way of doing that?

Not sure which version you're using, I was able to solve this using the latest stable version of CefSharp (47.0.0).
First add a handler to the FrameLoadEnd event:
browser.FrameLoadEnd += OnBrowserFrameLoadEnd;
The handler is the following:
private void OnBrowserFrameLoadEnd(object sender, FrameLoadEndEventArgs frameLoadEndEventArgs)
{
if (frameLoadEndEventArgs.Frame.IsMain && frameLoadEndEventArgs.Url == pageUrl)
{
frameLoadEndEventArgs.Browser.MainFrame.ExecuteJavaScriptAsync(
"(function() { var el = document.querySelector('a[href=\"" + linkUrl +
"\"]'); if(el) { el.scrollIntoView(); } })();");
}
}
The two constants are:
private const string pageUrl = "http://stackoverflow.com/";
private const string linkUrl = "http://stackexchange.com/legal";
Whenever we navigate to the site in the pageUrl, we invoke a JavaScript function in the loaded document. It selects the first element which has an href attribute equal to the linkUrl using querySelector. If there is an element like that, then we invoke the scrollIntoView() method on it.
This particular example scrolls the following link into view when you visit stackoverflow.com.
I used the CefSharp Minimal Example as a starting point to build my POC.
I uploaded it HERE for inspection.
Rebuild the project, package restore is enabled, so it should get all the necessary packages. After that you can run it. Enter stackoverflow.com into the address bar, hit Enter, and when it's loaded, the view should scroll down.

Related

Add hyperlink and trigger click event

I know there are a lot of these questions out there. However, the problem I am running into is that I am building out the javascript and/or jquery (tried both) from a C# page that creates a hyperlink, uses ScriptManager to register a startup script and triggers the click event.
The reason I want to do this instead of redirecting the window is sometimes I need to be able to change the target of the link to a blank window. That is where I'm running into the issue. The link is being created without issue, and added to the page and the click event is being fired. But when the target is _blank it is actually opening in a popup window instead of a new tab within the browser. The popup window is the same as a window.open().
There are other static links on my page with target=_blank and they open in a new tab without issue. Just the link that is being created behind the scenes and triggered with javascript open this way. Any ideas?
Pure Javascript Approach:
string js = #"var link = document.createElement('a');
link.href='{0}';
link.target='{1}';
document.body.appendChild(link);
link.click();
link.remove();";
string link = String.Format(js, url, target);
JQuery Approach:
string js = #"$('document').ready(function(){{
$('<a id=""tmpLink"" href=""{0}"" target=""{1}""></a>').appendTo('body');
$('a#tmpLink').trigger('click');
}});";

How to set the Selected item in the tree view on the Left side of CHM file

I have a CHM helpfile for my WPF Application. My CHM file contains "htm" files for each page of my application. I want to open the help file for the corresponding page when the user presses F1 on that page. Right now I am able to locate the page and open that page by using the following code:
Help.ShowHelp(this, helpfile, keywordText);
where keywordText contains the URL of my htm file for the selected page.
But the problem is, that the panel on the left side (contents tab in a tree view) is not expanded to the page that opened in the right window. The panel on the left side always remains the same.
How Can I expand the tree view on the left side to the selected page?
Have a look at the code and the small GUI (snap attached). The topics are refreshed after the users button click (e.g. Help Topic1).
Please note the help file created with Microsoft HTMLHelp Workshop may need a auto sync parameter.
private void btnHelpTopic1_Click(object sender, EventArgs e)
{
// sHTMLHelpFileName_ShowWithNavigationPane = "CHM-example_ShowWithNavigationPane.chm"
// This is a HelpViewer Window with navigation pane for show case only
// created with Microsoft HTMLHelp Workshop
helpProvider1.HelpNamespace = Application.StartupPath + #"\" + sHTMLHelpFileName_ShowWithNavigationPane;
Help.ShowHelp(this, helpProvider1.HelpNamespace, #"/Garden/tree.htm");
}
private void btnHelpTopic2_Click(object sender, EventArgs e)
{
helpProvider1.HelpNamespace = Application.StartupPath + #"\" + sHTMLHelpFileName_ShowWithNavigationPane;
Help.ShowHelp(this, helpProvider1.HelpNamespace, #"/Garden/flowers.htm");
}
For download I provide a C# VS2008 Project including the code above and the help files with different help viewer windows (different CHM files for show case only).
Thanks.
The Problem is in the URL.
Before that I gave a URL like this
"Help.CHM::/html/MyHelp.htm"
And when I removed "Help.CHM::/" from the URL and Everything Worked Well..

WebBrowser control doesn't populate on first iteration if loading two controls

The issue I am having is I have a WebBrowser control called "Browser." The browser is populated from a different controls created by MEF:
//Apply Button that cretes the HTML that is loaded into the Browser
btnCreateHTMLPreview(object sender, RoutedEventArgs e)
{
//Clears the content of the observable collection
contents.Clear();
//usedControls is an observable collection of all loaded controls in the stack panel
foreach(var control in usedControls)
control.CreateHTML();
}
//Code in the MEF Control that creates the HTML that is will be loaded into the browser
CreateHTML()
{
string tempStuff = null;
tempStuff += "<h1>" + MyControl.lblHeader.Content + "</h1>\n";
tempStuff += MyControl.txtTextGoesHere.Text + "\n";
//Give the HTML back to the Application
parent.AcceptReport(tempStuff);
}
//Application side where it accepts the HTML and loads it into the Browser
AcceptHTML(string passedInContent)
{
//Observable collection that holds the content of all possible MEF Controls
contents.Add(passedInContent);
string tempStuffForBrowser = null;
tempStuffForBrowser = "<html>\n";
tempStuffForBrowser += "<body>\n";
//Add the content that was saved earlier
foreach (var strInd in contents)
tempStuffForBrowser += strInd;
tempStuffForBrowser = "<html>\n";
tempStuffForBrowser += "<body>\n";
Browser.NavigateToString(tempStuffForBrowser);
}
I did my best above to try and provide the meat of how I am populating the html and add that back into the browser. If there is anything that is unclear please just let me know.
If I have just one control added so that "content" only has the one control in it when I click the button to load the html, it works just fine and loads it in. However if I have more than one control loaded, I have to click that button twice to get it to show. I found this extremely bizarre. My attempt to solve this was to check and see if there was content in the Browser before leaving the event, but I am unsure how to do this. If anyone has any suggestions or any other ideas on how to solve this problem please let me know.
It looks like the WebBrowser control has some kind of issue where it doesn't load the first string it gets; I'm assuming there's some initialization that hasn't happened yet. I got it to work by calling
myBrowser.NavigateToString("");
from within the constructor of my class, and then using it from then on worked correctly. Hokey but it works.

Web Browser control click

I am using Web Browser control in my project and i open a web that have file chooser object.
Now i want to inject programmatically a path to a file in this file chooser object .
I tried to get the HtmlElement ,but i not found in the source code the element Id.
Edit:
In the web there is "Browse..." button that open a file chooser,and then the file path is show in little text filed, and i want to inject the file path my self to the text field.
First.
establish a name, id or class for the element you want to change the value of. There are a number of ways of doing this. I would use firebug for firefox, or IE developer toolbar, or just view the source of the page and establish what the name/Id of the field is. Now if that field does not have a Name or an ID that you can use you might be able to get the containing element and iterate through the Child elements n times until you get the element you want.
For my embedded browser app I did the following in c#:-
// webBrowser is the name of the embedded IE browser in your app
var htmlDocument = webBrowser.Document;
if(htmlDocment!=null)
{
var field = htmlDocument.GetElementById("...the id...");
if(field!=null)
{
field.SetAttribute("value","...yourfilenamepathonyourmachine...");
}
// Now you would need to establish the ID of the submit element and click that
var submitButton = htmlDocument.GetElementById("...submit button...");
if(submitButton!=null)
{
submitButton.InvokeMember("Click");
}
// your code to loop?
}
So do you have the HTML of the page in question? that might help and a better answer can be given
Regards Julian

Opening a browser and filling in some data

i want to know how i can open a browser to a specific web page and then fill out some of the content of the boxes on that page.
My idea is for someone to be able to order a particular item from our internal ordering system. The barcodes for these items are what will populate the fields on the page i want to open.
I no i can open a new instance of ie using Process.Start("IEXPLORE.EXE", url); howver how do i get a handle on that exact ie instance window so i can begin to add the required data to the fields?
Is this even possible?
Thanks very much
WatiN should help with this. I've generally used it for acceptance testing of web apps, but the principle is the same. Open a browser instance, reference stuff in the DOM, manipulate form elements, etc.
In addition to WatiN (as was suggested in another answer), you might consider a load testing package like Web Performance Load Tester. They have a free version that lets you run up to 10 virtual users at a time, which will perform scripted actions.
Another option would be to use a standard WebBrowser object to load your website. The WebBrowser object allows you to access and alter certain web parts. Below is sample code that automatically searches Bing:
private void LoadPage()
{
WebBrowser webBrowser1 = new WebBrowser();
webBrowser1.Navigate("http://www.bing.com");
//Wait for document to load...
while (webBrowser1.ReadyState != WebBrowserReadyState.Complete)
{
Application.DoEvents();
}
//Set the text of the search input
HtmlElement txtTextField = webBrowser1.Document.GetElementById("sb_form_q");
txtTextField.InnerText = "My test text";
//Perform a click on the search button
HtmlElement btnSubmit = webBrowser1.Document.GetElementById("sb_form_go");
btnSubmit.InvokeMember("click");
}

Categories