Hello everyone, I'm the Wolf at the End of the Desert.
This article introduces how to embed a webpage using CefSharp in C# WPF, and presents a simple example demonstrating the interaction between C# and the webpage (JavaScript).
1. Steps to Build the Example
First, here is the sample code for this article: WpfWithCefSharpDemo.
1. Create a Project
Create a WPF project, for example named "WpfWithCefSharpDemo". A WinForms project is similar.
2. Create a Web Page
The embedded webpage can be online (by providing a URL) or an offline HTML page. For demonstration, this article creates a webpage test.html directly in the project, with the property Build Action set to Content and Copy to Output Directory set to Copy if newer.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>CefSharp Test</title>
<script>
// Test calling C# method from JavaScript
function callCSharpMethod() {
window.cefSharpExample.testMethod("Call from JS");
}
// Test C# calling JavaScript method, only passing a normal string
function displayMessage(message) {
alert(message);
}
// Receive JSON object from C# and display it in a table on the page
function displayJson(json) {
var obj = JSON.parse(json);
var html = "<table border='1'>";
for (var prop in obj) {
html += "<tr>";
html += "<td>" + prop + "</td>"
html += "<td>" + obj[prop] + "</td>"
html += "</tr>"
}
html += "</table>";
document.getElementById("jsonTable").innerHTML = html;
}
</script>
</head>
<body>
<h1>CefSharp Test</h1>
<button onclick="callCSharpMethod()">Call C# Method</button>
<div id="jsonTable"></div>
</body>
</html>
The code above includes relevant comments, which should be clear:
- JS method
callCSharpMethod: used to test calling a C# method from JS.cefSharpExampleis an object registered in C#, andtestMethodis one of its methods. Note that the first letter of the method name in JavaScript is lowercase (while in C# it is uppercase by convention) — this difference must be noted. - JS methods
displayMessageanddisplayJson: used to test calling JS methods from C#. They are similarly defined; the former takes a normal string as input, the latter takes a JSON string. - The
divelementjsonTableis used to display the JSON object data passed from C#.
3. Add the CefSharp Package
Install the CefSharp package. You can search for CefSharp.Wpf in the NuGet Package Manager in Visual Studio and install it.
4. Add the CefSharp Control
In MainWindow.xaml, import the CefSharp.Wpf namespace (using an alias wpf, which is optional), add the chromium control to the window, and also add a few test buttons:
<Window x:Class="WpfWithCefSharpDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:wpf="clr-namespace:CefSharp.Wpf;assembly=CefSharp.Wpf"
mc:Ignorable="d"
Title="WPF Loading CefSharp Test" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="35"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="50"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Text="Below shows the web page content"></TextBlock>
<Border Grid.Row="1" BorderBrush="DarkOrange" BorderThickness="2">
<wpf:ChromiumWebBrowser x:Name="Browser" Loaded="Browser_OnLoaded">
</wpf:ChromiumWebBrowser>
</Border>
<Border Margin="3 5" Grid.Row="2" BorderBrush="Blue" BorderThickness="2" VerticalAlignment="Center">
<StackPanel Orientation="Horizontal" Height="35">
<TextBlock Text="Buttons on the right are WPF buttons" VerticalAlignment="Center" Margin="5 3"></TextBlock>
<Button Content="Call JS Method" Click="CallJSFunc_Click" Height="30" Padding="10 2"></Button>
<Button Content="C# Pass Json Object to Webpage" Click="SendJsonToWeb_Click" Height="30" Padding="10 2"></Button>
</StackPanel>
</Border>
</Grid>
</Window>
5. Call JavaScript Methods from C#
In MainWindow.xaml.cs, add event handlers for the relevant controls, i.e., the code to call JavaScript methods from C#:
using CefSharp;
using Newtonsoft.Json;
using System;
using System.IO;
using System.Text;
using System.Windows;
namespace WpfWithCefSharpDemo
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// Allow registering C# objects to JavaScript in a synchronous manner
Browser.JavaScriptObjectRepository.Settings.LegacyBindingEnabled = true;
CefSharpSettings.WcfEnabled = true;
// The code to register C# objects to JavaScript must be called before the Cef Browser is loaded
Browser.JavaScriptObjectRepository.Register("cefSharpExample", new CefSharpExample(), false,
options: BindingOptions.DefaultBinder);
}
/// <summary>
/// After the Cef browser control is loaded, load the webpage content.
/// You can load a URL or the content directly.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Browser_OnLoaded(object sender, RoutedEventArgs e)
{
var htmlFile = $"{AppDomain.CurrentDomain.BaseDirectory}test.html";
if (!File.Exists(htmlFile))
{
return;
}
var htmlContent = File.ReadAllText(htmlFile, Encoding.UTF8);
Browser.LoadHtml(htmlContent);
}
/// <summary>
/// Call a general JavaScript method from C#
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void CallJSFunc_Click(object sender, RoutedEventArgs e)
{
var jsCode = $"displayMessage('Call from C#')";
Browser.ExecuteScriptAsync(jsCode);
}
/// <summary>
/// Call a JavaScript method from C# and pass a JSON object
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void SendJsonToWeb_Click(object sender, RoutedEventArgs e)
{
var jsonContent = new
{
Id = 1,
Name = "Wolf at the End of the Desert",
Age = 25,
WebSite = "https://dotnet9.com"
};
var jsonStr = JsonConvert.SerializeObject(jsonContent);
// Pass JSON object as a JSON string, similar to the previous example
var jsCode = $"displayJson('{jsonStr}')";
Browser.ExecuteScriptAsync(jsCode);
}
}
public class CefSharpExample
{
public void TestMethod(string message)
{
Application.Current.Dispatcher.Invoke(() => { MessageBox.Show("Call from JS"); });
}
}
}
CefSharpExample encapsulates the class and method definitions for JS calls. Note that in C#, the method name TestMethod starts with an uppercase letter, while in the HTML page created earlier, the call uses a lowercase first letter. This difference must be kept in mind again.
6. Results Display
JS calling C# method: The yellow border shows the webpage content. Click the HTML button Call C# Method to test.

C# calling a general JS method: The blue border shows WPF controls. Click the WPF button Call JS Method to test.

C# passing a JSON object to JS: Within the blue border, click the WPF button C# Pass Json Object to Webpage to test.

2. Summary
Please complete the above example. If you have used the WPF or WinForms native WebBrowser control, we will conclude this article by comparing the strengths and weaknesses of the WPF native WebBrowser control versus CefSharp (based on ChatGPT's response). Feel free to leave comments for discussion:
Advantages of the WPF native WebBrowser control:
- The WebBrowser control is built-in with WPF, requiring no additional libraries or components.
- The WebBrowser control is based on the Internet Explorer engine, offering natural compatibility and stability on Windows operating systems.
- The WebBrowser control provides many browser-related events, such as Navigating, Navigated, LoadCompleted, etc., allowing control and feedback over webpage loading and navigation.
Disadvantages of the WPF native WebBrowser control:
- The WebBrowser control uses an older version of the IE engine, does not support modern HTML5, CSS3 standards, and performance is inferior to CefSharp.
- The WebBrowser control has a relatively limited API, making it difficult to implement advanced features such as intercepting webpage navigation, custom rendering, etc.
Advantages of CefSharp:
- CefSharp is built on the Chromium project, supporting the latest HTML5, CSS3, and other web standards, with superior performance.
- CefSharp provides a rich API, enabling many advanced features such as custom network requests, intercepting webpage navigation, modifying HTML content, etc.
- CefSharp uses a multi-threaded model and hardware-accelerated rendering, does not block the UI thread, and offers better stability and security.
Disadvantages of CefSharp:
- CefSharp requires additional libraries or components, increasing development complexity.
- CefSharp may experience performance issues in certain scenarios, such as rendering on high-density screens.
Therefore, when choosing a web browser control, you need to decide based on your specific requirements. If you simply need to display webpage content without many advanced features, the WPF native WebBrowser control may suffice. However, if you need complex functionality such as custom network requests or intercepting webpage navigation, CefSharp may be more suitable. Overall, CefSharp provides more powerful capabilities and better performance compared to the WPF native WebBrowser, but it is also relatively more complex to use.
References:
Application of Mutual Calls between C# and JS Functions in CefSharp
WeChat Technical Exchange Group: Add WeChat (codewf) with note "Join Group"
QQ Technical Exchange Group: 771992300.
