CefSharp资源处理器的应用与示例

本文是关于CefSharp系列教程的延续,旨在解释CefSharp是什么以及如何使用它在WPF中显示HTML文档。本教程部分专注于CefSharp中的ResourceHandler,它是处理网络请求的一种方式。

ResourceHandler在CefSharp中非常有用,尤其是在需要显示静态HTML页面时。截至目前,ResourceHandler是同步执行的,因此应该谨慎使用,以避免阻塞网络请求。一个典型的应用场景是,当用户在浏览器应用的URL部分输入"about"字符串时,可以显示一个"关于"页面。

当然,"关于"页面并不是唯一的应用场景。ResourceHandler接口在CefSharp中的另一个有趣应用是作为查看器应用程序,它可以将文件内容(例如:Markdown)转换为HTML以供查看。还有其他用例,比如实现Windows中的控制面板页面。但这种用例在这里没有覆盖,而且可能更冒险地使用SchemeHandler来实现,将在本系列的下一篇文章中解释。

使用代码

"关于ResourceHandler示例项目"演示了想要将URL与在实现时已知的静态内容关联的简单案例。应用程序在启动时显示一个"关于"页面,并允许加载该页面链接的页面。还有一个单独的"测试URL 2"页面,可以通过鼠标点击加载。

以下是驱动应用程序的XAML代码,位于MainWindow.xaml文件中:

<Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Grid Grid.Row="0"> <Grid.Resources> <conv:InverseBooleanConverter x:Key="InverseConv"/> </Grid.Resources> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <Button Content="About" Command="{Binding TestUrlCommand}" IsEnabled="{Binding ElementName=browser, Path=IsLoading, Converter={StaticResource InverseConv}}"/> <Button Content="MarkDown" Grid.Column="1" Command="{Binding TestUrl1Command}" CommandParameter="{Binding ElementName=browser}" IsEnabled="{Binding ElementName=browser, Path=IsLoading, Converter={StaticResource InverseConv}}"/> <Button Content="Dev Tools" Grid.Column="2" Command="{Binding DevToolsCommand}" CommandParameter="{Binding ElementName=browser}" IsEnabled="{Binding ElementName=browser, Path=IsLoading, Converter={StaticResource InverseConv}}"/> </Grid> <cefSharp:ChromiumWebBrowser Grid.Row="1" Address="{Binding BrowserAddress, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Title="{Binding BrowserTitle, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" Name="browser"/> <StatusBar Grid.Row="2"> <TextBlock Name="Status" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/> </StatusBar> </Grid>

可以看到MainWindow由三部分组成:顶部的按钮列表、中间的名为browser的CefSharp浏览器控件,以及显示页面加载信息的状态栏。

让看看顶部的按钮是如何工作的。MainWindows.xaml代码绑定到一个名为AppViewModel的viewModel类,该类存储在"KnowledgeBase/ViewModels/AppViewModel.cs"中。这个viewmodel提供了两个命令属性,分别称为TestUrlCommand和TestUrl1Command。当点击"关于"按钮时,第一个命令被调用,第二个命令在点击"测试URL 2"按钮时被调用。

上述每个命令所做的工作并不多,只是设置AppViewModel类的BrowserAddress属性:

BrowserAddress = TestResourceUrl; BrowserAddress = TestUnicodeResourceUrl;

这个属性反过来与MainWindow.xaml中看到的CefSharp web浏览器控件绑定。那么,CefSharp是如何知道每个URL的含义,并且为什么它实际上显示自定义HTML呢?答案隐藏在MainWindow构造函数中,其中调用了AppViewModel.RegisterTestResources(browser);方法,参数为ChromiumWebBrowser实例:

public MainWindow() { InitializeComponent(); AppViewModel.RegisterTestResources(browser); DataContext = new AppViewModel(); browser.StatusMessage += BrowserStatusMessage; browser.NavStateChanged += BrowserNavStateChanged; }

注册每个ResourceHandlers的代码相当简单:

public static void RegisterTestResources(IWebBrowser browser) { var factory = browser.ResourceHandlerFactory; if (factory != null) { const string responseBody = "<html><body><h1>About</h1>" ... + "</body></html>"; factory.RegisterHandler(TestResourceUrl, ResourceHandler.FromString(responseBody)); const string unicodeResponseBody = "<html><body>整体满意度</body></html>"; factory.RegisterHandler(TestUnicodeResourceUrl, ResourceHandler.FromString(unicodeResponseBody)); } }

代码采用一个URL(定义在TestResourceUrl或TestUnicodeResourceUrl中)并将其与在字符串中定义的HTML内容(responseBody或unicodeResponseBody)关联。因此,每当IWebBrowser控件(实际上是MainWindow.xaml中的ChromiumWebBrowser实例)被请求加载任一URL时,它通过加载上述预定义的HTML字符串来实现这一点。

Markdown ResourceHandler示例

Sample2文件夹还包含一个"Sample 2 MarkDown ResourceHandler"应用程序,该应用程序可用于在WPF应用程序中查看Markdown内容。这个示例应用程序包含了Markdown转换器项目的副本。以下是用户点击Markdown按钮时显示的内容的截图:

这看起来并不那么有趣,它只是普通的HTML,但这个HTML是基于Markdown语法的,比HTML更容易编辑。内容的实际来源存储在示例应用程序的KnowledgeBase/SampleData/Readme.md文件中。

这个示例应用程序的工作原理与上面讨论的"关于"示例应用程序非常相似。但它在某些角落和地方略有不同。这个应用程序通过在App.xaml中配置的App.xaml.cs启动方法启动:

private void Application_Startup(object sender, StartupEventArgs e) { var mainWindow = new MainWindow(); var viewModel = new AppViewModel(); viewModel.RegisterTestResources(mainWindow.browser); mainWindow.DataContext = viewModel; mainWindow.Show(); }

AppViewModel类中的RegisterTestResources方法从KnowledgeBase项目中的SampleData子文件夹中加载示例markdown文本:

这个应用程序的工作原理与上面讨论的"关于"示例应用程序非常相似,不同之处在于,该应用程序可以根据文件系统(在bin/Debug或bin/Release文件夹中)中存储的Readme.md文件生成半静态内容。

这个示例应用程序还实现了一种刷新功能。实际上,可以在运行时编辑并保存Readme.md文件,然后点击Markdown按钮,在示例应用程序的窗口中看到编辑结果。

理解这个刷新功能的重要代码部分是以下几行:

RegisterMarkdownTestResources(browser); BrowserAddress = TestMarkDown2HTMLConversion;

在TestUrl1Command属性中。当用户点击Markup时执行此命令。第一行重新加载Markdown文件,将其转换为HTML并存储在字符串中,第二行更改当前地址以通知浏览器新的请求。

备注

请务必查看MainWindow.xaml.cs中的BrowserNavStateChanged(object sender, NavStateChangedEventArgs e)和BrowserStatusMessage(object sender, StatusMessageEventArgs e)方法,以了解如何更新MainWindow的状态栏和标题部分。

值得指出的是,示例应用程序扩展了http地址方案。CefSharp中的ResourceHandler也可以与自定义URI一起使用,例如:about,但这需要自定义SchemeHandler,将在本系列的下一篇文章中解释。

示例还包含AppViewModel类中的Dev Tools按钮和命令部分:

Chrome开发工具可用于验证和调试应用程序中加载的HTML、Javascript或CSS样式的状态。只需将鼠标悬停在某个部分上,例如上面的截图中的h1,就可以看到应用程序主窗口中的相应高亮显示。

[1] 在WPF和CefSharp中显示HTML教程第1部分 http://www.codeproject.com/Articles/881315/Display-HTML-in-WPF-and-CefSharp-Tutorial-Part

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485