WPF 媒体元素加载行为无法正常工作?



我正在 WPF 中创建一个简单的应用程序,其中包含 VB.NET 代码。此代码完美运行。选择文件后,该函数根据媒体类型返回正确的数字,当媒体是音频文件时出现注释图像,当不是音频文件时,注释图像消失。媒体会自动播放。但是,我不需要自动播放媒体,当我将"加载行为"设置为"手动"(而不是默认播放)时,会发生奇怪的事情。MediaOpened 事件不时触发,该函数有时返回零,有时返回正确的数字,有时返回不正确的数字。我在谷歌上搜索了将近三天,我什么也没找到。我想让 MediaElement.Play 和 MediaElement.Pause 显示视频/图像的第一帧,但如果没有将 LoadedBehavior 设置为手动,这是不可能的。我想以某种方式避免加载行为。有人可以给我一个提示吗?提前非常感谢你。

Private Sub btnFile_Click(sender As Object, e As RoutedEventArgs) Handles btnFile.Click
Try
Me.MediaElementSetting.LoadedBehavior = MediaState.Manual
Me.MediaElementSetting.UnloadedBehavior = MediaState.Close
Me.MediaElementSetting.Stop()
Me.MediaElementSetting.Close()
Me.PvwTimer.Stop()
Catch ex As Exception
'The exception occurs when LoadedBehavior is not set to manual, that's why it's unused
'MsgBox(ex.ToString)
End Try
Dim ArrayIndes as Integer = 1
OpenFileDialog(ArrayIndex)
End Sub
Sub OpenFileDialog(ByVal ArrayIndex As Integer)
Dim Dlg1 As New System.Windows.Forms.OpenFileDialog
Dlg1.ShowDialog()
If Dlg1.FileName <> "" Then
strFile = Dlg1.FileName
Me.MediaElementSetting.Source = New Uri(strFile, UriKind.RelativeOrAbsolute)
End If
End Sub
Private Sub MediaElementSetting_MediaOpened(sender As Object, e As RoutedEventArgs) Handles MediaElementSetting.MediaOpened
Dim t As Integer = AV()
End Sub
Function AV() As Integer
'Check, if the media has timespan (if it is image, audio, video w sound, video w/o sound - image has video without timespan)
If Me.MediaElementSetting.NaturalDuration.HasTimeSpan = True Then
If Me.MediaElementSetting.HasAudio = True Then
If Me.MediaElementSetting.HasVideo = True Then
'Media is a video with sound
MediaInfo = 4
Else
'Media is an audio
MediaInfo = 2
End If
Else
If Me.MediaElementSetting.HasVideo = True Then
'Media is a video without sound
MediaInfo = 3
End If
End If
Else
If Me.MediaElementSetting.HasVideo = True Then
'Media is an image
MediaInfo = 1
End If
End If
If MediaInfo = 2 Then
'Note is an image in a window. When the media is an audio it covers the mediaelement in a window
Note.Visibility = Visibility.Visible
Else
Note.Visibility = Visibility.Hidden
End If

Return MediaInfo
End Function

我不是一个 VB.NET 的人,但这里有一个 C# 中的工作示例。

下面是 XAML。我有一个MediaElement,一个Border作为笔记图像的替身,还有一个按钮。

MainWindow.xaml

<Window x:Class="SO.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SO"
Title="MainWindow"
Width="800"
Height="450">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<MediaElement x:Name="MediaElementSetting"
Margin="16" />
<Border x:Name="AudioElement"
Margin="16"
Background="Red"
Visibility="Collapsed">
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
Foreground="White"
Text="AUDIO" />
</Border>
<Button x:Name="FileButton"
Grid.Row="1"
Margin="16"
Padding="8,4"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Click="FileButton_OnClick"
Content="File" />
</Grid>
</Window>

下面是代码隐藏。

我在窗口的构造函数中初始化MediaElement一次。

为了显示视频的第一帧,我需要设置ScrubbingEnabled = true

OpenFileDialog()中,设置Source后我调用SetupMedia它立即调用PlayPause,然后设置Position。这可确保调用MediaOpened事件。

OnMediaOpened处理程序中,我调用GetMediaInfo它就像您的AV函数一样,而不是返回整数,而是返回一个枚举。

MainWindow.xaml.cs

using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms;
namespace SO
{
public partial class MainWindow : Window
{
private bool isMediaOpened;
public MainWindow()
{
InitializeComponent();
MediaElementSetting.LoadedBehavior = MediaState.Manual;
MediaElementSetting.ScrubbingEnabled = true;
MediaElementSetting.UnloadedBehavior = MediaState.Close;
MediaElementSetting.MediaOpened += OnMediaOpened;
}
private void OnMediaOpened(object sender, RoutedEventArgs e)
{
isMediaOpened = true;
var mediaInfo = GetMediaInfo();
Debug.WriteLine($"{mediaInfo}");
}
private void SetupMedia()
{
MediaElementSetting.Play();
MediaElementSetting.Pause();
MediaElementSetting.Position = TimeSpan.FromSeconds(0);
}
private MediaInfo GetMediaInfo()
{
var mediaInfo = MediaInfo.None;
if (MediaElementSetting.NaturalDuration.HasTimeSpan)
{
if (MediaElementSetting.HasAudio)
{
mediaInfo = MediaElementSetting.HasVideo ? MediaInfo.VideoWithSound : MediaInfo.Audio;
}
else
{
if (MediaElementSetting.HasVideo)
{
mediaInfo = MediaInfo.VideoNoSound;
}
}
}
else
{
if (MediaElementSetting.HasVideo)
{
mediaInfo = MediaInfo.Image;
}
}
AudioElement.Visibility = mediaInfo == MediaInfo.Audio ? Visibility.Visible : Visibility.Collapsed;
return mediaInfo;
}
private void FileButton_OnClick(object sender, RoutedEventArgs e)
{
OpenFileDialog();
}
private void OpenFileDialog()
{
var dialog = new OpenFileDialog();

dialog.ShowDialog();
if (!string.IsNullOrEmpty(dialog.FileName))
{
if (isMediaOpened)
{
MediaElementSetting.Source = null;
isMediaOpened = false;
}
MediaElementSetting.Source = new Uri(dialog.FileName, UriKind.RelativeOrAbsolute);
SetupMedia();
}
}
public enum MediaInfo
{
None = 0,
Image = 1,
Audio = 2,
VideoNoSound = 3,
VideoWithSound = 4
}
}
}

好吧,我意外地找到了非常适合我的解决方案。不使用 MediaElement.LoadedBehavior = 手动

Private Sub MediaElementSetting_MediaOpened(sender As Object, e As RoutedEventArgs) Handles MediaElementSetting.MediaOpened
Dim t As Integer = AV()
Me.MediaElementSetting.UnloadedBehavior = MediaState.Close
Me.MediaElementSetting.LoadedBehavior = MediaState.Play
Me.MediaElementSetting.LoadedBehavior = MediaState.Pause
End Sub

并使用MediaElement.LoadedBehavior控制媒体。这对我非常有效,即使我认为它不正确。从逻辑上讲,加载行为意味着加载行为。

Sub PlayMedia()
MediaElementSetting.LoadedBehavior = MediaState.Play
End Sub
Sub PauseMedia()
MediaElementSetting.LoadedBehavior = MediaState.Pause
End Sub
Sub StopMedia()
MediaElementSetting.LoadedBehavior = MediaState.Stop
End Sub

最新更新