介绍

重新想象 Windows 8 Store Apps 之 WebView


  • 演示 WebView 的基本应用
  • 演示 WebView 如何与 JavaScript 交互
  • 通过 Share Contract 分享 WebView 中的内容
  • 如何全屏 WebView


示例

1、WebView 的基本应用

WebView/Demo.xaml


<Page     x:Class="XamlDemo.Controls.WebView.Demo"     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"     xmlns:local="using:XamlDemo.Controls.WebView"     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"     mc:Ignorable="d">      <Grid Background="Transparent">         <StackPanel Margin="120 0 0 0">              <Button Name="btnNavigateUrl" Content="导航到指定的 url" Click="btnNavigateUrl_Click_1" />                          <Button Name="btnShowHtml" Content="解析指定的 html 字符串" Click="btnShowHtml_Click_1" Margin="0 10 0 0" />              <Button Name="btnFullScreen" Content="演示当 WebView 全屏时如何操作当前页(WebView 会遮挡所有元素)" Click="btnFullScreen_Click_1" Margin="0 10 0 0" />              <WebView Name="webView" Width="400" Height="300" HorizontalAlignment="Left" Margin="0 10 0 0" />                      </StackPanel>     </Grid> </Page>


WebView/Demo.xaml.cs


/*  * WebView - 内嵌浏览器  *     Source - 导航到指定的 url  *     Navigate() - 导航到指定的 url  *     NavigateToString() - 解析指定的 html 字符串  *     LoadCompleted - 在 DOM 加载完成后所触发的事件  *     NavigationFailed - 导航发生错误时触发的事件(事件参数:WebViewNavigationFailedEventArgs)  *       * WebViewNavigationFailedEventArgs  *     Uri - 尝试导航到的 Uri  *     WebErrorStatus - 错误状态(Windows.Web.WebErrorStatus 枚举)  */  using System; using Windows.UI.Popups; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls;  namespace XamlDemo.Controls.WebView {     public sealed partial class Demo : Page     {         public Demo()         {             this.InitializeComponent();         }          private void btnNavigateUrl_Click_1(object sender, RoutedEventArgs e)         {             // 导航到指定的 url             webView.Navigate(new Uri("javascript:void(0)", UriKind.Absolute));             // webView.Source = new Uri("javascript:void(0)", UriKind.Absolute);              // 导航失败时             webView.NavigationFailed += webView_NavigationFailed;         }          async void webView_NavigationFailed(object sender, WebViewNavigationFailedEventArgs e)         {             await new MessageDialog(e.WebErrorStatus.ToString()).ShowAsync();         }          private void btnShowHtml_Click_1(object sender, RoutedEventArgs e)         {             // 解析指定的 html 字符串             webView.NavigateToString("<html><body>I am webabcd</body></html>");         }          private void btnFullScreen_Click_1(object sender, RoutedEventArgs e)         {             var root = Window.Current.Content as Windows.UI.Xaml.Controls.Frame;             root.Navigate(typeof(XamlDemo.Controls.WebView.FullScreen));         }     } }


2、WebView 如何与 JavaScript 交互

WebView/Interact.xaml


<Page     x:Class="XamlDemo.Controls.WebView.Interact"     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"     xmlns:local="using:XamlDemo.Controls.WebView"     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"     mc:Ignorable="d">      <Grid Background="Transparent">         <StackPanel Margin="120 0 0 0">              <Button Name="btnInvokeJavaScript" Content="app 调用 WebView 加载内容中的 JavaScript 脚本" Click="btnInvokeJavaScript_Click_1" />              <Button Name="btnAccessDOM" Content="通过 eval 访问 DOM" Click="btnAccessDOM_Click_1" Margin="0 10 0 0" />              <WebView Name="webView" Width="400" Height="300" Source="http://localhost:39629/WebViewInteract.html" HorizontalAlignment="Left" Margin="0 10 0 0" />          </StackPanel>     </Grid> </Page>


WebView/Interact.xaml.cs


/*  * 演示 app 如何与 WebView 中的 JavaScript 进行交互  *   * WebView - 内嵌浏览器  *     InvokeScript() - 调用 JavaScript 中的指定函数,并返回执行结果  *     ScriptNotify - 当接收到从 JavaScript 发过来的数据时所触发的事件(事件参数:NotifyEventArgs)  *     AllowedScriptNotifyUris - 允许触发 ScriptNotify 事件的 uri 列表  *       * NotifyEventArgs  *     Value - js 传递给 app 的数据  *   *       * 注:本例通过加载 WebServer 项目下的 WebViewInteract.html 来演示 app 与 js 的交互  */  using System; using System.Collections.Generic; using Windows.UI.Popups; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Navigation;  namespace XamlDemo.Controls.WebView {     public sealed partial class Interact : Page     {         public Interact()         {             this.InitializeComponent();              // 指定允许触发 ScriptNotify 事件的 uri 列表(如果 uri 是目录而不是文件,则此目录下所有文件都可以触发 ScriptNotify 事件)             List<Uri> allowedUris = new List<Uri>();             allowedUris.Add(new Uri("http://localhost:39629/"));             webView.AllowedScriptNotifyUris = allowedUris;              webView.ScriptNotify += webView_ScriptNotify;         }          async void webView_ScriptNotify(object sender, NotifyEventArgs e)         {             // 获取 js 传递过来的数据(js 端通向 app 传递数据的方法:window.external.notify('js to app');)             await new MessageDialog(e.Value).ShowAsync();         }          // app 调用 js         private async void btnInvokeJavaScript_Click_1(object sender, RoutedEventArgs e)         {             string[] arguments = { "webabcd" };             // 调用 js 方法:sayHelloToJs('webabcd'); 并返回结果             string result = webView.InvokeScript("sayHelloToJs", arguments);              await new MessageDialog(result).ShowAsync();         }          // 通过 eval 方式访问 DOM         private async void btnAccessDOM_Click_1(object sender, RoutedEventArgs e)         {             // 获取 document.title 的值             string[] arguments = { "document.title" };             string result = webView.InvokeScript("eval", arguments);              await new MessageDialog(result).ShowAsync();         }     } }


3、通过 Share Contract 分享 WebView 中的内容

WebView/Share.xaml


<Page     x:Class="XamlDemo.Controls.WebView.Share"     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"     xmlns:local="using:XamlDemo.Controls.WebView"     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"     mc:Ignorable="d">      <Grid Background="Transparent">         <StackPanel Margin="120 0 0 0">              <Button Name="btnShare" Content="通过 Share Contract 分享 WebView 中的被选中的文本内容" Click="btnShare_Click_1" />                          <WebView Name="webView" Width="400" Height="300" Source="javascript:void(0)" HorizontalAlignment="Left" Margin="0 10 0 0" />                      </StackPanel>     </Grid> </Page>


WebView/Share.xaml.cs


/*  * 演示如何通过 Share Contract 分享 WebView 中的内容(复制到剪切板也是同理)  *   * WebView - 内嵌浏览器  *     DataTransferPackage - 返回 DataPackage 对象  */  using Windows.ApplicationModel.DataTransfer; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls;  namespace XamlDemo.Controls.WebView {     public sealed partial class Share : Page     {         private DataTransferManager _dataTransferManager;          public Share()         {             this.InitializeComponent();         }                  private void btnShare_Click_1(object sender, RoutedEventArgs e)         {             _dataTransferManager = DataTransferManager.GetForCurrentView();             _dataTransferManager.DataRequested += _dataTransferManager_DataRequested;              DataTransferManager.ShowShareUI();         }          // 分享 WebView 中的被选中的文本内容         void _dataTransferManager_DataRequested(DataTransferManager sender, DataRequestedEventArgs args)         {             DataRequest request = args.Request;             DataPackage dataPackage = webView.DataTransferPackage;             DataPackageView dataPackageView = dataPackage.GetView();              // 如果用户选择了一段内容,则通过 WebView.DataTransferPackage 获取到的数据里就会有 StandardDataFormats.Text 格式的内容,此内容就是用户所选中的内容             if (dataPackageView.Contains(StandardDataFormats.Text))              {                 dataPackage.Properties.Title = "Title";                 dataPackage.Properties.Description = "Description";                  request.Data = dataPackage;             }             else             {                 request.FailWithDisplayText("没有选中任何内容");             }              _dataTransferManager.DataRequested -= _dataTransferManager_DataRequested;         }     } }


4、全屏 WebView 时需要注意哪些

WebView/FullScreen.xaml


<Page     x:Class="XamlDemo.Controls.WebView.FullScreen"     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"     xmlns:local="using:XamlDemo.Controls.WebView"     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"     mc:Ignorable="d">      <Page.Resources>         <Storyboard x:Name="sbOpenAppBar">             <DoubleAnimation x:Name="aniTranslateYOpen" Storyboard.TargetName="webView" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)" Duration="00:00:00.367">                 <DoubleAnimation.EasingFunction>                     <ExponentialEase EasingMode="EaseOut"/>                 </DoubleAnimation.EasingFunction>             </DoubleAnimation>         </Storyboard>         <Storyboard x:Name="sbCloseAppBar">             <DoubleAnimation x:Name="aniTranslateYClose" Storyboard.TargetName="webView" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)" Duration="00:00:00.367">                 <DoubleAnimation.EasingFunction>                     <ExponentialEase EasingMode="EaseOut"/>                 </DoubleAnimation.EasingFunction>             </DoubleAnimation>         </Storyboard>     </Page.Resources>          <Page.BottomAppBar>         <AppBar x:Name="appBar">             <StackPanel Orientation="Horizontal">                 <Button x:Name="btnHome" Style="{StaticResource HomeAppBarButtonStyle}" Click="btnHome_Click_1" />             </StackPanel>         </AppBar>     </Page.BottomAppBar>      <Grid Background="Transparent">         <WebView Name="webView" Source="javascript:void(0)">             <WebView.RenderTransform>                 <CompositeTransform/>             </WebView.RenderTransform>         </WebView>     </Grid> </Page>


WebView/FullScreen.xaml.cs


/*  * 由于 WebView 控件上不允许显示其他任何元素,那么当 WebView 全屏时如何操作当前页呢?  * 可以考虑通过 AppBar 操作当前页面,但是 AppBar 也会被 WebView 挡住,所以我们要做的是当 AppBar 显示后,减小 WebView 的高度  *   * 注:WebViewBrush 上是可以显示其他元素的  */  using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Navigation;  namespace XamlDemo.Controls.WebView {     public sealed partial class FullScreen : Page     {         public FullScreen()         {             this.InitializeComponent();         }          protected override void OnNavigatedTo(NavigationEventArgs e)         {             appBar.Opened += appBar_Opened;             appBar.Closed += appBar_Closed;         }          protected override void OnNavigatedFrom(NavigationEventArgs e)         {             appBar.Opened -= appBar_Opened;             appBar.Closed -= appBar_Closed;         }          // 显示 BottomAppBar,减小 WebView 的高度,使其不会遮挡 BottomAppBar         void appBar_Opened(object sender, object e)         {             // 强制更新布局,这样可以获取到 WebView 和 BottomAppBar 的最新的真实高度             this.UpdateLayout();              double appBarHeight = appBar.ActualHeight;             webView.Height = webView.ActualHeight - appBarHeight;              // WebView 的高度减小后会居中显示,此方法用于将 WebView 的顶端和屏幕的顶端对齐,同时来个动画效果             aniTranslateYOpen.To = -appBarHeight / 2.0;             sbOpenAppBar.Begin();         }          // appBar_Opened 的逆运算,不解释         void appBar_Closed(object sender, object e)         {             this.UpdateLayout();              double appBarHeight = appBar.ActualHeight;             webView.Height = webView.ActualHeight + appBarHeight;              aniTranslateYOpen.To = appBarHeight / 2.0;             sbCloseAppBar.Begin();         }          // 导航到首页         private void btnHome_Click_1(object sender, RoutedEventArgs e)         {             var root = Window.Current.Content as Windows.UI.Xaml.Controls.Frame;             root.Navigate(typeof(XamlDemo.MainPage));         }     } }



OK