当MediaElement切换到FullWindow模式时,内部FullWindowMediaRoot将成为其临时主机。当可见时,FullWindowMediaRoot位于普通RootScrollViewer的顶部,即它显示为当前页面的覆盖层,这是预期的行为。
我的问题是BottomAppBar。它的主机是内部的PopupRoot,不幸的是它位于FullWindowMediaRoot之上。因此,当我在允许用户将MediaElement切换到FullWindow的页面上使用BottomAppBar时,用户无法使用MediaElement的控件,因为这些元素几乎完全被仍然可见的BottomAppBar隐藏。
我已经为这个问题花了将近一天的时间,找到了一个对我有效的解决方案。如果有人有更好的答案,我会很感激与大家分享。在那之前,我会在下面为遇到同样问题的人记录我目前的工作解决方案。
我的解决方案使用了一个实现IValueConverter的类,每当MediaElement的IsFullWindow属性更改值时,它就会引发一个事件。
页面初始化程序向转换器的FullWindowStateChanged事件添加一个事件处理程序:
this.isFullWindowConverter.FullWindowStateChanged += this.OnFullWindowStateChanged;
并像这样处理:
/// <summary>
/// Handles the FullWindowStateChanged event of IsFullWindowConverter by adjusting the visibility of the BottomAppBar to the full window
/// state of this page's MediaElement.
/// </summary>
/// <param name="sender">The instance of IsFullWindowConverter raising the event.</param>
/// <param name="e">The parameter is not used.</param>
private void OnFullWindowStateChanged(object sender, EventArgs e)
{
this.BottomAppBar.Visibility = ((IsFullWindowConverter)sender).IsFullWindow ? Visibility.Collapsed : Visibility.Visible;
}
这里的转换器类别:
namespace Filmit.Win
{
using System;
using Windows.UI.Xaml.Data;
/// <summary>
/// This converter raises an event when the IsFullWindow property of a MediaElement has changed. The converter is added to the resources of the page that hosts the MediaElement:
/// <code><local:IsFullWindowConverter x:Key="isFullWindowConverter" x:Name="isFullWindowConverter"/></code>
/// This converter resource is then bound to the IsFullWindow property of a MediaElement, solely for the event raising effects of the ConvertBack method this converter.
/// The actual value of the IsFullWindow property is returned as is.
/// <code><MediaElement IsFullWindow="{Binding RelativeSource={RelativeSource Self}, Path=IsFullWindow, Converter={StaticResource isFullWindowConverter}, Mode=TwoWay}"></code>
/// The subscriber to the FullWindowStateChanged event checks the IsFullWindow property to get the current full window state of the MediaElement.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1603:DocumentationMustContainValidXml", Justification = "XAML Page.Resources declaration.")]
public class IsFullWindowConverter : IValueConverter
{
/// <summary>
/// Raises the FullWindowStateChanged event. Subscribers check the IsFullWindow property to get the current full windows state.
/// </summary>
public event EventHandler<EventArgs> FullWindowStateChanged = null;
/// <summary>
/// Gets a value indicating whether the mode of the MediaElement is FullWindow.
/// </summary>
public bool IsFullWindow { get; private set; }
/// <summary>
/// Required implementation of IValueConverter.Convert, returning the passed in boolean object as a bool.
/// </summary>
/// <param name="value">The boolean object.</param>
/// <param name="targetType">The expected target type.</param>
/// <param name="parameter">The parameter is not used.</param>
/// <param name="language">The parameter is not used.</param>
/// <returns>The passed in boolean object as a bool.</returns>
public object Convert(object value, Type targetType, object parameter, string language)
{
bool? isFullWindow = value as bool?;
this.IsFullWindow = isFullWindow.HasValue ? isFullWindow.Value : false;
return this.IsFullWindow;
}
/// <summary>
/// This implementation of IValueConverter.ConvertBack is called when the IsFullWindow property of the MediaElement has changed its value.
/// It raises the FullWindowStateChanged event and returns the passed in boolean object as a bool.
/// </summary>
/// <param name="value">The boolean object.</param>
/// <param name="targetType">The expected target type.</param>
/// <param name="parameter">The parameter is not used.</param>
/// <param name="language">The parameter is not used.</param>
/// <returns>The passed in boolean object as a bool.</returns>
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
bool? isFullWindow = value as bool?;
this.IsFullWindow = isFullWindow.HasValue ? isFullWindow.Value : false;
if (this.FullWindowStateChanged != null)
{
this.FullWindowStateChanged(this, new EventArgs());
}
return this.IsFullWindow;
}
}
}
如果您正在创建一个UWP应用程序,我认为您可以在Grid
中放置一个AppBar
,并将其定位到页面底部。这也会解决你的问题。但如果你正在使用windows 8.1应用程序,这种方法将不起作用。
XAML:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<MediaElement x:Name="MyMedia" Source="Assets/Sofia Jannok-Liekkas.wma" AreTransportControlsEnabled="True" />
<AppBar VerticalAlignment="Bottom">
<CommandBar>
<CommandBar.Content>
<Grid/>
</CommandBar.Content>
<AppBarButton Icon="Accept" Label="appbarbutton"/>
<AppBarButton Icon="Cancel" Label="appbarbutton"/>
<AppBarButton Content="Maximize" VerticalAlignment="Center" HorizontalAlignment="Center" Click="maximize"/>
</CommandBar>
</AppBar>
</Grid>
C#:
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
public void maximize(object sender, RoutedEventArgs e)
{
MyMedia.IsFullWindow = !MyMedia.IsFullWindow;
}
}
无论如何,你的解决方案都能解决问题。感谢您的分享。