cefsharp / CefSharp

.NET (WPF and Windows Forms) bindings for the Chromium Embedded Framework
http://cefsharp.github.io/
Other
9.84k stars 2.92k forks source link

Can't load a new address on Form.Load or Form.Shown #537

Closed rfgamaral closed 9 years ago

rfgamaral commented 9 years ago

I'm trying to develop this simple Windows Forms application using CefSharp but I've hit some walls which I can't seem to overcome.

Here's an oversimplified example of my problem:

class MainForm : Form {

    private readonly ChromiumWebBrowser chromium;

    public MainForm() {
        InitializeComponent();

        chromium = new ChromiumWebBrowser("www.google.com") {
            Dock = DockStyle.Fill,
            MenuHandler = new BrowserMenuHandler()
        };

        browserPanel.Controls.Add(chromium);
    }

    private void MainForm_Load(object sender, System.EventArgs e) {
        chromium.Load("www.bing.com");
    }

    private void MainForm_Shown(object sender, System.EventArgs e) {
        chromium.Load("www.yahoo.com");
    }

}

After Application.Run(new MainForm()); the form is displayed and google is loaded, but bing and yahoo are never loaded. Shouldn't they be? What am I doing wrong here?

amaitland commented 9 years ago

@rfgamaral Which version of CefSharp are you using? e.g. 33.0.2, 33.1.0-pre01, custom build?

rfgamaral commented 9 years ago

I was using 33.0.1 and then saw 33.0.2 was released and updated to that. Both had the same issue. I can try the 33.1.0-pre01 if you need me to and see if it helps.

rfgamaral commented 9 years ago

I tried 33.1.0-pre01 but the problem persisted. I also tried to call chromium.Load() on chromium.IsBrowserInitializedChanged event but it still didn't work. But if I add a button to the form and call chromium.Load() there, it works just fine.

It seems that somehow CEF or the ChromiumWebBrowser is not fully initialized and I need to wait for that before calling chromium.Load(), but how do I do that since IsBrowserInitializedChanged is not working for me?

rfgamaral commented 9 years ago

I found the following workaround...

First added chromium.NavStateChanged += chromium_NavStateChanged; in the constructur before adding chromium to browserPanel. Then I have this event handler:

private void chromium_NavStateChanged(object sender, CefSharp.NavStateChangedEventArgs e) {
    if(!e.CanGoBack && !e.CanGoForward && e.CanReload) {
        chromium.Load("www.bing.com");
        chromium.NavStateChanged -= chromium_NavStateChanged;
    }
}

This works for now but I still think that it should somehow work on the form's Load and Shown events. Or is there a good reason for it not to work and I should keep my workaround?

amaitland commented 9 years ago

The form's Load and Shown events don't really tie into the ChromiumWebBrowser. Based on the code above, just checking for e.CanReload would be enough, that identifies the browser is finished loading.

What exactly is it that your trying to achieve? What's your scenario? Is there any particular reason your loading an initial URL, then trying to load a different URL immediately after?

rfgamaral commented 9 years ago

The form's Load and Shown events don't really tie into the ChromiumWebBrowser. Based on the code above, just checking for e.CanReload would be enough, that identifies the browser is finished loading.

I just wanted to be sure that this was the first load and not something else. Checking if it can go back or forward further assures this. But I guess it's not really needed and e.CanReload will do the trick given my whole code.

What exactly is it that your trying to achieve? What's your scenario? Is there any particular reason your loading an initial URL, then trying to load a different URL immediately after?

The only reason I'm doing that is because of #522, otherwise I would be loading it just once somewhere else (not in the constructor). The thing is, the address that I'll be loading depends on user input which comes from a different form. However, due to some particularities of my application, the MainForm needs to be created - but not shown - right when the application starts and that is before I ask for the user input. As such I need this workaround.

I'll probably finish the whole thing by the weekend, I would love to show the end result to you guys and if you could spare a few minutes to give some input on the implementation (just the CefSharp related bits, not the whole thing) that would be great. But I understand if you guys are busy :)

amaitland commented 9 years ago

Ahh, #522!

I'd probably go with FrameLoadEnd event, just because I know it's called only once (when you don't have any frames). So perhaps just initially chromium = new ChromiumWebBrowser("about:blank"), then

private void BrowserFrameLoadEnd(object sender, FrameLoadEndEventArgs e)
{
  if (e.IsMainFrame)
  {
    browser.Load("http://github.com");
    browser.FrameLoadEnd -= BrowserFrameLoadEnd;
  }
}

Hopefully once #522 is resolved a lot of these little issues are resolved!

I'll probably finish the whole thing by the weekend, I would love to show the end result to you guys and if you could spare a few minutes to give some input on the implementation (just the CefSharp related bits, not the whole thing) that would be great. But I understand if you guys are busy :)

Post away, can't make any guarantees. If I've got time next week I'll have a look :smile:

rfgamaral commented 9 years ago

What exactly is the MainFrame? I didn't use that because I was not sure what it meant so I went with e.CanReload because it just worked the way I was expected since any other event before I could reload, the Load didn't seem to work. I just want to know if it makes more sense to use e.IsMainFrame or if I should just keep e.CanReload.

I know this is not a forum and it's not a good place for it, but can I create a new issue for posting the app when it's done? Or if you'd prefer some other way of contact, let me know...

amaitland commented 9 years ago

What exactly is the MainFrame?

Returns the main (top-level) frame for the browser window.. Basically if you have a standard web page without frames then LoadEnd will only be called once with IsMainFrame = true, if you had a html document with frames, or iframes then IsMainFrame = true for the parent, e.g. top most in the tree.

If your more comfortable with NavStateChanged then go with that, it's called a lot more times (actually unnecessarily called a lot more times, I've created a PR to fix that). As your interested in the first time, then unwiring the event handler, it won't be a problem.

I know this is not a forum and it's not a good place for it, but can I create a new issue for posting the app when it's done? Or if you'd prefer some other way of contact, let me know..

Just keep things simple and post here for now, others with similar issues might find your code useful :smile:

rfgamaral commented 9 years ago

I'll have to check if I can do it on BrowserFrameLoadEnd because I have something there already that also unbinds the event handler. One or the other will have to do :)

I'll be posting the whole project her eon GitHub so I'll just share the link in this issue when I release it and we can close the issue around that time. Sounds good?

amaitland commented 9 years ago

I'll have to check if I can do it on BrowserFrameLoadEnd because I have something there already that also unbinds the event handler. One or the other will have to do :)

Once we've moved to the next version of Cef, then #522 can be revisited, looks like it should be fixable, just needs some time digging through the cefclient sample and the cef forum.

I'll be posting the whole project her eon GitHub so I'll just share the link in this issue when I release it and we can close the issue around that time. Sounds good?

:+1:

rfgamaral commented 9 years ago

I've finished the first release of my application using CefSharp:

If you guys have the time to look at the source code, let me know if I'm doing something stupid :D

rfgamaral commented 9 years ago

I'll close this issue as not to pollute your project. Let me know if you guys have any comments to make. My latest developments are on the develop branch.

amaitland commented 9 years ago

@rfgamaral You should be able to remove the hack once #547 is fully tested and merged. Feel free to take it for a spin before hand (it does require an upgrade to 2062, which will shortly become the latest official CefSharp release version`)

rfgamaral commented 9 years ago

I'd need to compile myself, right?

amaitland commented 9 years ago

For now yes, shouldn't be too long before there's a new Nuget package available for testing.

rfgamaral commented 9 years ago

I'd rather wait for that. But thanks for the heads up :)