A Dockable Web Browser

The Revit API supports add-ins defining their own dockable panels, similar to the built-in Revit project browser and element properties panels.

Here is The Building Coder topic list of Dockable Panel related discussions:

I have repeatedly been asked bow to host a web browser in a dockable panel, and this query yesterday finally prompted me to take the plunge:

Question: I am working on a project for Revit learning content and I would like to implement an add-in that opens a dockable window and basically opens a browser in that window that points to a URL (local or internet based). I found this post on a simpler dockable panel sample.

Through a little bit of hacking I figured out how to make it work for Revit 2015. I thought maybe by looking at it I could figure out how the dockable window was populated and figure out how to launch a browser in there, but no luck. I really have no clue when it comes to Revit API and coding at all.

Is this something you can help me with? I feel like it is probably a pretty simple change to get this sample to open a browser in the window instead of whatever is there. I could install the HTML files local I want to point at, but ideally it would allow me to put any URL as the destination. I want to point at a specific Learning Content website I am working on, but would also like it to be able to allow a customer to point to their own internal learning content.

Any help you could give would be great. I am trying to get a simple mock-up working so I can get someone interested enough in the concept to give me some development resources to make it a real feature in Revit.

Answer: Here is a bit of research and a pointer to an existing blog post or two that might help answer the question:

First, you need code to open the HTML page. That should happen automatically if you launch the HTML page using Process.Start. That should open the browser on that page.

The use of Process.Start in a Revit add-in is described in launching a stand-alone executable.

Oh dear, I see that you want the browser in your own window.

Cool that you already found and made use of the Simpler Dockable Panel Sample!

I was going to suggest that next.

Well, the third step would be to host a browser in that window.

If IE is enough of a browser for you, you can use the Microsoft .NET browser control, e.g. as described by CodeProject on using the WebBrowser control in .NET.

There are alternatives to the built-in IE browser, and they obviously require more work, e.g., replacing the .NET WebBrowser control with a better browser like Chrome.

Since you went to the effort to migrate the original DockableDialog sample to Revit 2015, others will probably be interested in that as well. I therefore created a DockableDialog GitHub repository for it and repeated that exercise.

You say, "Through a little bit of hacking I figured out how to make it work for Revit 2015."

My migration was totally straightforward and required no hacking whatsoever.

You might want to compare your version with mine, and take a look at the minimal changes I made for the migration.

The flat migrated add-in is provided in version 2015.0.0.0, and the changes from the Revit 2014 version are encapsulated in this commit.

Response: “Hacking” was probably the wrong word, or means something different to a guy like me who has NEVER written a line of code. The ZIP file I downloaded did not want to run in 2015, so I had to figure out how to make changes to get it going. It was all I could do to stumble through that. :-)

Answer: Well done!

Next step: I now implemented a web browser in the dockable panel sample.

Check out the GitHub version 2015.0.0.1.

Added a XAML web browser control, and you can click the buttons at the top to switch between The Building Coder and GitHub:

DockableWebBrowser docked

This provides the proof of concept you require.

You could also use WinForms instead of WPF, so more .NET and C# rather than XAML, if you prefer that.

Good luck and have fun!

Script Error

Displaying The Building Coder web page hosted by Typepad in the WebBrowser control generates an error message saying, "An error has occurred in the script on this page":

DockableWebBrowser script error

I searched for a solution for that.

I started looking up this error and found things like how to handle script errors as a WebBrowser control host and script error in web browser.

That was not what I wanted, so I narrowed it down by searching for 'disable' as well, discovering how to disable JavaScript error in WebBrowser control and make use of the WebBrowser.ScriptErrorsSuppressed property.

Unfortunately, the WPF control does not implement this property, so a further search for 'wpf web browser control disable script error' turned up numerous solutions such as how to disable script errors WebBrowser WPF, which is exactly what I need.

I added two URL definitions to the add-in XAML code, pointing to The Building Coder and this DockableDialog sample GitHub repository:

  const string _url_tbc = "http://thebuildingcoder.typepad.com";
  const string _url_git = "https://github.com/jeremytammik/DockableDialog";

Here is the resulting XAML driver code driving the buttons to toggle the browser location back and forth between these two URLs and disable the JavaScript warning messages triggered by the Typepad framework hosting The Building Coder:

  private void PaneInfoButton_Click(
    object sender,
    RoutedEventArgs e )
  {
    web_browser.Navigate( _url_tbc );
  }
 
  private void wpf_stats_Click(
    object sender,
    RoutedEventArgs e )
  {
    web_browser.Navigate( _url_git );
  }
 
  private void btn_getById_Click(
    object sender,
    RoutedEventArgs e )
  {
    web_browser.Navigate( _url_tbc );
  }
 
  private void btn_listTabs_Click(
    object sender,
    RoutedEventArgs e )
  {
    web_browser.Navigate( _url_git );
  }
 
  private void DockableDialogs_Loaded(
    object sender,
    RoutedEventArgs e )
  {
    web_browser.Navigated += new NavigatedEventHandler(
      WebBrowser_Navigated );
 
    web_browser.Navigate( _url_tbc );
  }
 
  void WebBrowser_Navigated(
    object sender,
    NavigationEventArgs e )
  {
    HideJsScriptErrors( (WebBrowser) sender );
  }
 
  public void HideJsScriptErrors( WebBrowser wb )
  {
    // IWebBrowser2 interface
    // Exposes methods that are implemented by the 
    // WebBrowser control
    // Searches for the specified field, using the 
    // specified binding constraints.
 
    FieldInfo fld = typeof( WebBrowser ).GetField(
      "_axIWebBrowser2",
      BindingFlags.Instance | BindingFlags.NonPublic );
 
    if( null != fld )
    {
      object obj = fld.GetValue( wb );
      if( null != obj )
      {
        // Silent: Sets or gets a value that indicates 
        // whether the object can display dialog boxes.
        // HRESULT IWebBrowser2::get_Silent(VARIANT_BOOL *pbSilent);
        // HRESULT IWebBrowser2::put_Silent(VARIANT_BOOL bSilent);
 
        obj.GetType().InvokeMember( "Silent",
          BindingFlags.SetProperty, null, obj,
          new object[] { true } );
      }
    }
  }

As said, the complete code for this, Visual Studio solution and add-in manifest is provided in the DockableDialog GitHub repository, and the version described here is release 2015.0.0.3.