WebView 是 WinRT 內嵌瀏覽器控件,支援完整 HTML5/CSS3/JavaScript。但它是 獨立視窗層級 的原生控件,不允許任何 XAML 元素覆蓋其上方(Z-index 無效),這帶來全螢幕、AppBar 遮擋等特殊挑戰。本文涵蓋基礎導航、JS 雙向互通、Share Contract 分享、全螢幕模式下的 AppBar 共存技巧。
Source / Navigate(Uri):導航到 URLNavigateToString(string html):直接解析 HTML 字串LoadCompleted:DOM 載入完成事件NavigationFailed:導航失敗事件(WebViewNavigationFailedEventArgs.WebErrorStatus)<StackPanel Margin="120 0 0 0">
<Button x:Name="btnNavigateUrl" Content="導航到指定 URL" Click="btnNavigateUrl_Click"/>
<Button x:Name="btnShowHtml" Content="解析 HTML 字串" Click="btnShowHtml_Click" Margin="0 10 0 0"/>
<Button x:Name="btnFullScreen" Content="全螢幕 WebView 測試" Click="btnFullScreen_Click" Margin="0 10 0 0"/>
<WebView x:Name="webView" Width="400" Height="300" HorizontalAlignment="Left" Margin="0 10 0 0"/>
</StackPanel>
private void btnNavigateUrl_Click(object sender, RoutedEventArgs e)
{
webView.Navigate(new Uri("https://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(object sender, RoutedEventArgs e)
{
webView.NavigateToString("I am webabcd");
}
private void btnFullScreen_Click(object sender, RoutedEventArgs e)
{
var root = Window.Current.Content as Frame;
root.Navigate(typeof(FullScreen));
}
webView.InvokeScript("functionName", string[] args):呼叫 JS 函數並取得回傳值(字串)"eval":執行任意 JS 表達式(如 document.title)window.external.notify('message')webView.ScriptNotify 事件,NotifyEventArgs.Value 取得訊息webView.AllowedScriptNotifyUris 允許的來源 URI 列表<StackPanel Margin="120 0 0 0">
<Button x:Name="btnInvokeJS" Content="App 呼叫 WebView JS" Click="btnInvokeJS_Click"/>
<Button x:Name="btnAccessDOM" Content="透過 eval 存取 DOM" Click="btnAccessDOM_Click" Margin="0 10 0 0"/>
<WebView x:Name="webView" Width="400" Height="300"
Source="https://localhost:39629/WebViewInteract.html"
HorizontalAlignment="Left" Margin="0 10 0 0"/>
</StackPanel>
public sealed partial class Interact : Page
{
public Interact()
{
this.InitializeComponent();
// 必須設定允許 ScriptNotify 的 URI
var allowedUris = new List<Uri> { new Uri("https://localhost:39629/") };
webView.AllowedScriptNotifyUris = allowedUris;
webView.ScriptNotify += webView_ScriptNotify;
}
async void webView_ScriptNotify(object sender, NotifyEventArgs e)
{
await new MessageDialog(e.Value).ShowAsync(); // 顯示 JS 傳來的訊息
}
private async void btnInvokeJS_Click(object sender, RoutedEventArgs e)
{
// 呼叫 JS: sayHelloToJs('webabcd')
string result = webView.InvokeScript("sayHelloToJs", new[] { "webabcd" });
await new MessageDialog(result).ShowAsync();
}
private async void btnAccessDOM_Click(object sender, RoutedEventArgs e)
{
// eval 取得 document.title
string result = webView.InvokeScript("eval", new[] { "document.title" });
await new MessageDialog(result).ShowAsync();
}
}
<script>
function sayHelloToJs(name) {
return "Hello " + name + " from JS!";
}
// 主動通知 App
window.external.notify("JS 主動送訊息給 App");
</script>
WebView.DataTransferPackage 回傳 DataPackage,包含使用者選取的文字/圖片/HTML/連結等格式。
<StackPanel Margin="120 0 0 0">
<Button x:Name="btnShare" Content="分享 WebView 選取文字" Click="btnShare_Click"/>
<WebView x:Name="webView" Width="400" Height="300"
Source="https://webabcd.cnblogs.com/"
HorizontalAlignment="Left" Margin="0 10 0 0"/>
</StackPanel>
public sealed partial class Share : Page
{
private DataTransferManager _dtm;
private void btnShare_Click(object sender, RoutedEventArgs e)
{
_dtm = DataTransferManager.GetForCurrentView();
_dtm.DataRequested += _dtm_DataRequested;
DataTransferManager.ShowShareUI();
}
void _dtm_DataRequested(DataTransferManager sender, DataRequestedEventArgs args)
{
var pkg = webView.DataTransferPackage;
var view = pkg.GetView();
if (view.Contains(StandardDataFormats.Text))
{
pkg.Properties.Title = "Title";
pkg.Properties.Description = "Description";
args.Request.Data = pkg;
}
else
{
args.Request.FailWithDisplayText("沒有選中任何內容");
}
_dtm.DataRequested -= _dtm_DataRequested;
}
}
問題:WebView 全螢幕時會遮擋所有 XAML 元素,包含 AppBar。
解法:AppBar.Opened 時縮減 WebView 高度並向上位移,AppBar.Closed 時恢復,並配合動畫平滑過渡。
<Page.BottomAppBar>
<AppBar x:Name="appBar">
<StackPanel Orientation="Horizontal">
<Button x:Name="btnHome" Style="{StaticResource HomeAppBarButtonStyle}" Click="btnHome_Click"/>
</StackPanel>
</AppBar>
</Page.BottomAppBar>
<Grid Background="Transparent">
<WebView x:Name="webView" Source="https://webabcd.cnblogs.com/">
<WebView.RenderTransform>
<CompositeTransform/>
</WebView.RenderTransform>
</WebView>
</Grid>
<Page.Resources>
<Storyboard x:Name="sbOpenAppBar">
<DoubleAnimation x:Name="aniTranslateYOpen"
Storyboard.TargetName="webView"
Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)"
Duration="0:0:0.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="0:0:0.367">
<DoubleAnimation.EasingFunction>
<ExponentialEase EasingMode="EaseOut"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</Page.Resources>
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;
}
void appBar_Opened(object sender, object e)
{
this.UpdateLayout(); // 強制佈局更新以取得實際高度
double h = appBar.ActualHeight;
webView.Height = webView.ActualHeight - h; // 縮減高度
aniTranslateYOpen.To = -h / 2.0; // 向上位移一半(置中效果)
sbOpenAppBar.Begin();
}
void appBar_Closed(object sender, object e)
{
this.UpdateLayout();
double h = appBar.ActualHeight;
webView.Height = webView.ActualHeight + h; // 恢復高度
aniTranslateYClose.To = h / 2.0;
sbCloseAppBar.Begin();
}
private void btnHome_Click(object sender, RoutedEventArgs e)
{
var root = Window.Current.Content as Frame;
root.Navigate(typeof(MainPage));
}
}
若需在 WebView 上方疊加 XAML 元素(如浮水印、註解),可使用 WebViewBrush 將 WebView 內容繪製到 Rectangle.Fill,然後隱藏原 WebView。WebViewBrush 上方可自由放置 XAML 元素。
Navigate/NavigateToString、LoadCompleted/NavigationFailedInvokeScript(App→JS)、ScriptNotify+AllowedScriptNotifyUris(JS→App)、eval 存取 DOMWebView.DataTransferPackage + DataTransferManagerAppBar.Opened/Closed 動態調整 WebView 高度與 RenderTransform.TranslateY 實現共存掌握這些技巧,即可在 App 中無縫整合豐富網頁內容,並解決全螢幕互動難題。