I am using the System.Windows.Forms.WebBrowser to display XML in a syntax highlighted and easy to traverse format. Whenever I load the XML into the Control, I would like to have all the elements collapsed, is this possible?
This is triggered by the DocumentCompleted event handler.
this was a useful link to help with java script injection:
How to execute custom JavaScript in WebBrowser control?
I used the following code.
private void CollapseExpandDocument(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (sender == null)
{
return;
}
try
{
WebBrowser me = (WebBrowser) sender;
HtmlElement head = me.Document.GetElementsByTagName("head")[0];
HtmlElement scriptEl = me.Document.CreateElement("script");
IHTMLScriptElement element = (IHTMLScriptElement)scriptEl.DomElement;
string func = #"
function collapseDoc()
{
var className = 'b';
var hasClassName = new RegExp('(?:^|\\s)' + className + '(?:$|\\s)');
var allElements = document.getElementsByTagName('a');
var element;
for (var i = 0; (element = allElements[i]) != null; i++)
{
var elementClass = element.className;
if (elementClass && elementClass.indexOf(className) != -1 && hasClassName.test(elementClass))
ch(element.parentElement.parentElement);
}
}";
element.text = func;
head.AppendChild(scriptEl);
me.Document.InvokeScript("collapseDoc");
}
catch
{
//not interested in knowing if the collapse/expand failed...
}
}
Related
i need to have a label where its text comes from a web page, but for somting it doesnt work out, it appearce to me that the webpae returned null, but the location is correct.
WebBrowser JOJO = new WebBrowser();
string Tesla = "";
JOJO.Url = new Uri("https://finance.yahoo.com/quote/TSLA?p=TSLA");
var sal = JOJO.Document.GetElementsByTagName("div");// this return null
foreach (HtmlElement link in sal)
{
if (link.GetAttribute("className") == "D(ib) Mend(20px)")/*this is the class of the element*/
{
Tesla = link.FirstChild.InnerHtml;
}
}
label11.Text = Tesla;
this is the code that i have done so far, can someone see why dosnt work?
Thanks.
It is null because it didn't load yet when you try to access it. You should be handling it asynchronously.
Handle the DocumentCompleted event and access the Document in the handler.
Replace the code you have with:
WebBrowser JOJO = new WebBrowser();
JOJO.DocumentCompleted += new System.Windows.Forms.WebBrowserDocumentCompletedEventHandler
(this.BrowserDocumentCompleted);
JOJO.Url = new Uri("https://finance.yahoo.com/quote/TSLA?p=TSLA");
And here is the handler:
void BrowserDocumentCompleted(object sender,
WebBrowserDocumentCompletedEventArgs e)
{
if (e.Url.AbsolutePath != (sender as WebBrowser).Url.AbsolutePath)
return;
string Tesla = "";
var sal = (sender as WebBrowser).Document.GetElementsByTagName("div");
foreach (HtmlElement link in sal)
{
if (link.GetAttribute("className") == "D(ib) Mend(20px)")
{
Tesla = link.FirstChild.InnerHtml;
}
}
label1.Text = Tesla;
}
Now you will maybe face other problems with redirections. But that is another discussion :)
My WinForms program uses a WebBrowser control, and it creates a new TabPage with a WebBrowser control inside whenever the NewWindow event is triggered, using the following code:
private void WebBrowser1_NewWindow(object sender, System.ComponentModel.CancelEventArgs e)
{//open new window in new browser tab
string newUrl = browser.Document.ActiveElement.GetAttribute("href");
string pageName = "Page " + (tabControl1.TabCount + 1).ToString();
TabPage detailsTab = new TabPage(pageName);
Button closeTab = new Button();
closeTab.Anchor = (AnchorStyles.Top | AnchorStyles.Right);
closeTab.Location = new Point(10, 10);
closeTab.Text = "Close Tab";
closeTab.Click += new EventHandler(btnCloseTab_Click);
tabControl1.TabPages.Add(detailsTab);
WebBrowser detailsBrowser = new WebBrowser();
detailsBrowser.Dock = DockStyle.Fill;
detailsBrowser.Navigate(newUrl);
detailsTab.Controls.Add(detailsBrowser);
detailsTab.Controls.Add(closeTab);
closeTab.BringToFront();
tabControl1.SelectedIndex = tabControl1.TabCount -1;
}
So that each time a new browser tab is opened, a WebBrowser control called detailsBrowser is added to that tab. The problem is, if I need to get an HTML element from that browser, using something like:
HtmlElement saveButton = detailsBrowser.Document.GetElementsByTagName("input").GetElementsByName("save")[0];
I have no idea which detailsBrowser will be used to pull that HtmlElement.
I tried using
tabControl1.SelectedTab.Controls["detailsBrowser"]
instead of just referencing the browser by name, but this doesn't work and returns null when I try to get an HtmlElement from the browser.
Does anyone have a recommendation for how to specify a control using its container when multiple controls have the same name? Or is there a way to give each programmatically generated WebBrowser control a unique name?
Thanks!
EDIT: Here's the method I'm trying to use with the WebBrowser to select HTML elements:
public void addNote(string noteText)
{
WebBrowser currentBrowser = (WebBrowser) tabControl1.SelectedTab.Controls["detailsBrowser"];
HtmlElement showNotesButton = null;
//var links = browser.Document.GetElementsByTagName("div");
var links = currentBrowser.Document.GetElementsByTagName("div");
foreach (HtmlElement link in links)
{
if (link.GetAttribute("className") == "user_info_link")
{
showNotesButton = link;
}
}
//HtmlElement noteBox = browser.Document.GetElementById("remark");
HtmlElement noteBox = currentBrowser.Document.GetElementById("remark");
//HtmlElement submitNote = browser.Document.GetElementById("save_note");
HtmlElement submitNote = currentBrowser.Document.GetElementById("save_note");
showNotesButton.InvokeMember("click");
noteBox.Focus();
noteBox.InnerText = noteText;
Thread.Sleep(50);
submitNote.InvokeMember("click");
}
I've strange problem... :/
I have on my page PlaceHolder, where I generate dynamically more PlaceHolders.
I've stored names of this dynamicaly created PlaceHolders.
When I try to find any of this PlaceHolders - I've got error null reference to an Object.
Please help! :)
private void btnMoreInfo_Click(object sender, EventArgs e)
{
Button button = sender as Button;
string[] componentName = button.ID.Split('_');
String controlName = null;
foreach (String singlePlaceHolder in placeHolderNames)
{
if (singlePlaceHolder.Contains(componentName[0]))
controlName = singlePlaceHolder;
}
Control cph = this.Master.FindControl(controlName);
Label helperlabel = new Label();
helperlabel.Text = "That one!";
cph.Controls.Add(helperlabel);
cph.Visible = true;
}
I changed code to this, and it's working now:
var cph = FindControlRecursive(this.Master, controlName);
plus I added new method:
private Control FindControlRecursive(Control root, string id)
{
if(root.Id==id)
{
return root;
}
foreach (Control c in root.Controls)
{
Control t= FindControlRecursaive(c, id);
if (t !=null)
{
return t;
}
}
return null;
}
when i try to run javascript in a webbrowser, the code runs, but after it has been executed takes me on a white page with the upper right corner a numeric value (in this case "1000"), taking me away from the site where I was previously
HtmlElement head = webBrowser1.Document.GetElementsByTagName("head")[0];
HtmlElement scriptEl = webBrowser1.Document.CreateElement("script");
IHTMLScriptElement element = (IHTMLScriptElement)scriptEl.DomElement;
element.text = "function ScrollDown() { document.getElementsByClassName('scrollableitemclass').scrollTop = 1000 }";
head.AppendChild(scriptEl);
webBrowser1.Document.InvokeScript("ScrollDown");
Thank you for the help
You can scroll to your Html Elemet with HtmlElement.ScrollIntoView.
see this example:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser1_DocumentCompleted);
}
private void Form1_Load(object sender, EventArgs e)
{
webBrowser1.DocumentText = "<html><body><span class=\"cls\" id=\"el\"> </body></html>";
}
void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
//for element with id
webBrowser1.Document.GetElementById("el").ScrollIntoView(true);
//for element with spesific
foreach (HtmlElement el in webBrowser1.Document.All)
{
if (el.GetAttribute("ClassName") == "cls")
{
el.ScrollIntoView(true);
}
}
}
}
I am putting together a WYSIWYG html editor using the .NET webbrowser control. I have managed to piece together the code for inserting a table at the cursor position. However I am now trying to do something a little different.
What I need to do is insert a and html comment around a table row. I've managed to write the code that, from the cursor position, looks to the parent elements to find the table row the curor is sat in. The problem is when I try to use the pastHtml method in the range, it throws an exception with no detail on why its failed!.
Code listed below.
private void OnTest(object sender, EventArgs e)
{
try
{
IHTMLDocument2 doc = wbDesign.Document.DomDocument as IHTMLDocument2;
IHTMLSelectionObject currentSelection = doc.selection;
if (currentSelection != null)
{
IHTMLTxtRange range = currentSelection.createRange() as IHTMLTxtRange;
bool foundRow = false;
IHTMLElement parentElement = null;
parentElement = range.parentElement();
if ("TR" == parentElement.tagName) foundRow = true;
while (!foundRow)
{
if (null == parentElement.parentElement) break;
parentElement = parentElement.parentElement;
if ("TR" == parentElement.tagName) foundRow = true;
}
if (foundRow)
{
currentSelection.clear();
range.moveToElementText(parentElement);
range.pasteHTML("test");
}
else
{
MessageBox.Show("Unable to find table row from selection point.");
}
}
}
catch (Exception error)
{
MessageBox.Show(error.Message);
}
}