I'm using WBC in my project but I don't need it to be added to the form, I tried to call Navigate method but still get empty string when retrieving
the WBC .DocumentTitle!
Navigate is asynchronous, that means it goes to that web page on another thread and does not wait until it finishes. You are trying to get the Title immediatelly, but it is not set yet.
You should attach to DocumentCompleted event on the WBC and check for title there.
As noted the title can only be retrieved after it has been set. To know when that happens, in addition to DocumentCompleted event there is also a WebBrowser.DocumentTitleChanged event that is convenient and could simplify your logic.
Also, presumably, the latter event would also fire when title changes after the document is loaded via Javascript.
Related
I would like to automatically scroll to the top of the ListView when the user navigates to this with the back button. I tried to use this:
scrollViewer.ScrollToVerticalOffset(0.0);
It works, but the VS says:
ScrollToVerticalOffset may be altered or unavailable for releases
after Windows 8.1. Instead, use ChangeView.
Okay, I thought it's no problem, I will use ChangeView instead of this. But the ChangeView doesn't work properly. At least in my case. I tried this:
scrollViewer.ChangeView(null, 0d, null);
It works when I call it for example from a button, but it doesn't do anything when I put it to the OnNavigatedTo method.
So why does it work?
If you take a look at MSDN description od OnNavigatedTo, you will see that it's called before the visual tree is loaded. Therefore if you want to manipulate your UI elements - do it in Loaded event:
You cannot use OnNavigatedTo for element manipulation or state change of controls on the destination page. Instead, attach a Loaded event handler at the root of the newly loaded page's content, and perform any element manipulations, state changes, event wiring and so on in the Loaded event handler.
IF a WebBrowser control is doing a Navigate() command, and before it finished I call another navigate command, does this cause on error does it simply start a new navigation and dump the old one?
Thanks!
The first Navigate command will simply be dumped. Naturally, it may however cause problems if you have event handlers following the initial Navigate that are still executing, expecting the page from the first Navigate.
It simply start a new navigation and dump the old one.
I won't produce any exceptions as long as you are not depending on custom code executed on the Navigating or ProgressChanged event handlers. The WebBrowser just cancels the current navigation and starts a new one.
I created a status strip on my main form and a label within it. And I am opening another form within this (MdiContainer is true). For opening I am passing the object of main form in the constructor i.e. this. There I am updating the text of the label but its not getting updated.
I tried invalidate function also.
I was having this problem too. The fix is to add a line of code that fires events (see the second line below)
MainForm.mainStatusLabel.Text = "Importing data file" //see next line
Application.DoEvents()
I don't completely understand why this works, but my guess is that VB does not handle Application-wide events in the middle of a method unless you tell it to. When you change the text property, this is an event. So VB will (Im guessing) wait until the end of the method before handling the event--unless you tell it specifically to handle all events with Application.DoEvents()
Instead of passing the instance of the MainForm to the ChildForm, define a custom event in the ChildForm, raise the event with the message that you want to show (as argument), then subscribe the event in MainForm, and in the eventhandler update the control text with the message. You may also have to check Control.InvokeRequired.
I also had the problem, in my case because the text was too long to be displayed (Contained an exception message.) I set the SizingGrip property to 'False', so my text was shown (but trunkated).
I'm trying to write a function that will dynamically create tab pages, populate the tabs, and then return data regarding what it has done. There are events that will tell me when each tab is done, so I'll be able to tell when they're all loaded.
All the work is UI-related, and my understanding is that UI stuff has to happen in the main thread, so it sounds like I can't just create a thread to do this and then wait on it in my function. Am I misunderstanding the issue with UI stuff having to be on the main thread? How can I have my function wait without blocking the work that has to happen in the UI?
EDIT: To clarify, the tab pages have webbrowser controls which will load various web pages, so those take some amount of time and I get a DocumentCompleted event for each when it's loaded. The idea is this: The caller hands me a list of urls. I pop up a form and create a tab page containing a web browser control for each url, and load one url in each tab. These will complete at different times, each firing a DocumentComplete event handler when a page has loaded. When they've all loaded, I want to return a list of data to the original caller.
...and my understanding is that UI stuff has to happen in the main thread...
No, that's not necessarily true. If you want to modify, let's say, a label from a background thread, you can do:
MethodInvoker m = () => { label1.Text = "Another text"; };
if (InvokeRequired) {
BeginInvoke(m);
}
else {
m.Invoke();
}
instead of:
label1.Text = "Another text";
If you are carefully with that, you won't have any cross-thread problems.
Edit:
Take a look at the answer I provided in the question Client Coding error for chatting application if you want to refactor a little bit that code.
Edit 2:
According to your edit, this is how I would do that:
Receive the urls from the user
Start each browser and a variable that will hold how many tabs you opened.
Start a progressbar or something that tells the user the application is working...
Everytime you receive a DocumentComplete event, you decrease the variable.
If the value of the variable is 0, then all pages were loaded.
Stop progress bar
Return the data you want to the user.
Now.. when will you need to use the Invoke? Everytime you want to access to some UI control from the background thread. In that case, when you're stopping the progress bar...
I am not sure I've got you right. Anyway, take a look at this:
How to update the GUI from another thread in C#?
I'm setting a HTML string value to webbrowser.DocumentText. Problem is, sometimes it worked and sometimes it hangs up and not go through the documentcompleted event. what might be the problem?
Please reply, asap..
Thanks,
Jepe
Just a thought: With all the web-'dynam-ism' nowadays, a page is never really in a 'completely-loaded' state. After DocumentComplete, the OnLoad event of the page is fired, then any scripts placed in such an event are fired, and then javascript timers may be used to initiate download/upload of some resource, or a change in page using AJAX, etc.
I believe AJAX calls could cause all kinds of unseen problems with your WebBrowser control; because AJAX can cause multiple Navigating() events to fire during the loading of a page. And for that reason your app would experience multiple DocumentCompleted event fire on that page.
A possible solution could be to monitor the page changes and attempt to find out what possibly got changed. And to do this you may need to look into Notify method.
Called by MSHTML when a change occurs
in the contents of the markup
container with which it is
associated.
This and this discussion may help you coming up with something like following:
HtmlElement target = _webBrowser.Document.GetElementById("somedivthatwillbepopulatedbytheajaxrequest");
if (target != null)
{
target.AttachEventHandler("onpropertychange", new EventHandler(handler));
}