How to display charms on a top of the WebView.
I've been moving along in my development of the FeedPoint app to WinRT. And as a good citizen of the Modern UI I needed to implement app contracts such as search, share and settings which become available for a user via charms. When displaying Accounts flyout in my app I've noticed that it doesn't show properly on the page that's using the WebView control because the flyout gets hidden behind the WebView:
This is happening because of the way the WebView control implemented and its internal drawing logic. This MSDN page suggests to use the WebViewBrush to overcome this issue by placing a rectangle with a snapshot on a top of the WebView. So I did the same. First I placed the Rectangle in my XAML after the WebView. This insures that the Rectangle will be on a top of the WebView:
<WebView x:Name="webViewContent" Grid.Column="2" Grid.Row="1" Margin="40,0,10,0" ScriptNotify="webViewContent_ScriptNotify">
<WebView.RenderTransform>
<CompositeTransform/>
</WebView.RenderTransform>
</WebView>
<Rectangle x:Name="webViewBrushRect" Visibility="Collapsed" Grid.Column="2" Grid.Row="1" Margin="40,0,10,0" />
Next, I've added SwitchWebView public method to the code behind of this page:
public void SwitchWebView(bool back)
{
if (!back)
{
WebViewBrush brush = new WebViewBrush();
brush.SourceName = "webViewContent";
brush.Redraw();
webViewContent.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
webViewBrushRect.Visibility = Windows.UI.Xaml.Visibility.Visible;
webViewBrushRect.Fill = brush;
}
else
{
webViewContent.Visibility = Windows.UI.Xaml.Visibility.Visible;
webViewBrushRect.Fill = new SolidColorBrush(Colors.Transparent);
}
}
This method creates a new WebViewBrush, assigns the source for it to be the name of the WebView control, changes visibility and assigns the brush to the Rectangle. This method needs to get called when a flyout becomes visible. It could be done in the constructor like this:
public AccountsUserControl()
{
this.InitializeComponent();
if (App.CurrentFrame != null)
{
if (App.CurrentFrame.CurrentSourcePageType.Name == "FeedPage")
{
var feedPage = (FeedPage)App.CurrentFrame.Content;
feedPage.SwitchWebView(false);
}
}
}
private void OnBackButtonClicked(object sender, RoutedEventArgs e)
{
if (this.Parent.GetType() == typeof(Popup))
{
((Popup)this.Parent).IsOpen = false;
if (App.CurrentFrame != null)
{
if (App.CurrentFrame.CurrentSourcePageType.Name == "FeedPage")
{
var feedPage = (FeedPage)App.CurrentFrame.Content;
feedPage.SwitchWebView(true);
}
}
}
SettingsPane.Show();
}
Don't forget to switch it back when the back button is clicked. Here's the screenshot of the result:
Comments
Anonymous
August 21, 2012
I have IsLightDismissEnabled enabled, so user can close the settings charm by tapping somewhere on the screen and OnBackButtonClicked isn't fired. What would be the correct event handler to catch that tap so that WebView could be reverted back to normal? Thanks!Anonymous
August 21, 2012
I ended up putting the code in the Closed event handler of the Popup that contains my SettingsFlyout. Thanks for the instructions though, helped a lot!Anonymous
October 11, 2012
But there is no App.CurrentFrame??? :/Anonymous
October 11, 2012
It's just this in the App.xaml.cs: public static Frame CurrentFrame { get { return Window.Current.Content as Frame; } }Anonymous
October 13, 2012
I owe you a chocolate :) Thank you.Anonymous
March 12, 2013
The comment has been removed