重新想象 Windows 8 Store Apps (8) - 控件之 WebView

简介: 原文:重新想象 Windows 8 Store Apps (8) - 控件之 WebView[源码下载] 重新想象 Windows 8 Store Apps (8) - 控件之 WebView 作者:webabcd介绍重新想象 Windows 8 Store Apps 之 WebView ...
原文: 重新想象 Windows 8 Store Apps (8) - 控件之 WebView

[源码下载]


重新想象 Windows 8 Store Apps (8) - 控件之 WebView



作者:webabcd


介绍
重新想象 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("http://webabcd.cnblogs.com/", UriKind.Absolute));
            // webView.Source = new Uri("http://webabcd.cnblogs.com/", 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="http://webabcd.cnblogs.com/" 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="http://webabcd.cnblogs.com/">
            <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
[源码下载]

目录
相关文章
|
26天前
|
Linux C++ Windows
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
|
26天前
|
Java 应用服务中间件 开发工具
[App Service for Windows]通过 KUDU 查看 Tomcat 配置信息
[App Service for Windows]通过 KUDU 查看 Tomcat 配置信息
|
26天前
|
Java 应用服务中间件 Windows
【App Service for Windows】为 App Service 配置自定义 Tomcat 环境
【App Service for Windows】为 App Service 配置自定义 Tomcat 环境
|
26天前
|
PHP Windows
【Azure App Service for Windows】 PHP应用出现500 : The page cannot be displayed because an internal server error has occurred. 错误
【Azure App Service for Windows】 PHP应用出现500 : The page cannot be displayed because an internal server error has occurred. 错误
|
27天前
|
PHP 开发工具 git
【Azure 应用服务】在 App Service for Windows 中自定义 PHP 版本的方法
【Azure 应用服务】在 App Service for Windows 中自定义 PHP 版本的方法
|
26天前
|
网络安全 API 数据安全/隐私保护
【Azure App Service】.NET代码实验App Service应用中获取TLS/SSL 证书 (App Service Windows)
【Azure App Service】.NET代码实验App Service应用中获取TLS/SSL 证书 (App Service Windows)
|
26天前
|
Shell PHP Windows
【Azure App Service】Web Job 报错 UNC paths are not supported. Defaulting to Windows directory.
【Azure App Service】Web Job 报错 UNC paths are not supported. Defaulting to Windows directory.
|
26天前
|
存储 Linux Windows
【应用服务 App Service】App Service For Windows 如何挂载Storage Account File Share 示例
【应用服务 App Service】App Service For Windows 如何挂载Storage Account File Share 示例
|
26天前
|
应用服务中间件 nginx Windows
【Azure 应用服务】在App Service for Windows中实现反向代理
【Azure 应用服务】在App Service for Windows中实现反向代理
|
27天前
|
网络协议 Linux 网络安全
【Azure 应用服务】更便捷的方式抓取Azure App Service for Windows的网络包
【Azure 应用服务】更便捷的方式抓取Azure App Service for Windows的网络包