如何确定 MediaElement 是不是正在播放?

Posted

技术标签:

【中文标题】如何确定 MediaElement 是不是正在播放?【英文标题】:How do I determine if MediaElement is playing?如何确定 MediaElement 是否正在播放? 【发布时间】:2011-05-19 08:17:38 【问题描述】:

看起来很简单,但我想不出任何方法来确定 MediaElement 的状态。某些状态(例如 IsBuffering)有各种属性,但我找不到播放、暂停等状态的任何属性。Silverlight 似乎有一个 CurrentState 属性可以显示所有这些。

目前,我确定是否应该播放视频的方式是观看各种事件和一个计时器,以检查是否正在取得任何进展。

我是 MediaElement 和 WPF 的新手(我实际上只在 WinForms 应用程序中使用 MediaElement)。有什么我遗漏的吗?

【问题讨论】:

【参考方案1】:

你没有错过任何东西。您几乎必须手动跟踪媒体是否正在播放。很遗憾,正如您所提到的,因为在 Silverlight 中这很容易。对我来说似乎是一个重大疏忽。

【讨论】:

我在 WPF GitHub 存储库中添加了一个关于此的功能请求。请去给它竖起大拇指。 Add CurrentState property to MediaElement #3655【参考方案2】:

您可以使用反射获取_currentState 成员。

    private MediaState GetMediaState(MediaElement myMedia)
    
        FieldInfo hlp = typeof(MediaElement).GetField("_helper", BindingFlags.NonPublic | BindingFlags.Instance);
        object helperObject = hlp.GetValue(myMedia);
        FieldInfo stateField = helperObject.GetType().GetField("_currentState", BindingFlags.NonPublic | BindingFlags.Instance);
        MediaState state = (MediaState)stateField.GetValue(helperObject);
        return state;
    

这包括播放/暂停,但完成后不会从“播放”变为“停止”。

您可以通过向MediaEnded 事件添加事件处理程序并运行.Stop() 方法来解决此问题,这会正确更改状态(可以通过上述方法获取)

【讨论】:

优秀的解决方案!这就是这样做的方法。 除非 Microsoft 将来某个时候重命名该字段 这对我来说非常有效。谢谢。我看到了重命名的潜在危险,但我们还有什么其他解决方案?下面引用的 CurrentState 在现代完整 WPF 中不存在。【参考方案3】:

我做了什么来“解决”子类 MediaPlayer(这也适用于 MediaElement)并将我自己的方法添加到播放/暂停/停止。在这些方法中,我维护了一个表示播放状态的字段。此外,您需要挂钩 MediaEnded 以便您可以将状态从“正在播放”更改为“已停止”。

【讨论】:

把它放在 CodePlex 上。如果你没有时间,我打算,只是不想踩到任何脚趾。【参考方案4】:

对于Universal Windows 10 Platform (UWP)

if ( yourMediaElement.CurrentState.ToString() == "Playing" ) 

    //nou yourMediaElement is playng

如果您想改用enum,则以下:

if (yourMediaElement.CurrentState == MediaElementState.Playing)

    //nou yourMediaElement is playng

【讨论】:

【参考方案5】:

并且可以基于 Rich S 实现扩展

//don't forget
using System.Windows.Controls;
using System.Reflection;


 public static class Util
    
     public static MediaState GetMediaState(this MediaElement myMedia)
        
            FieldInfo hlp = typeof(MediaElement).GetField("_helper", BindingFlags.NonPublic | BindingFlags.Instance);
            object helperObject = hlp.GetValue(myMedia);
            FieldInfo stateField = helperObject.GetType().GetField("_currentState", BindingFlags.NonPublic | BindingFlags.Instance);
            MediaState state = (MediaState)stateField.GetValue(helperObject);
            return state;
        
    

【讨论】:

【参考方案6】:

对于Silverlight,使用 CurrentState 检查状态是播放还是暂停

 if (YourMediaElementName.CurrentState == MediaElementState.Playing)
 
     // TODO: when media is playing.
 

【讨论】:

需要注意的是CurrentState只是Silverlight。【参考方案7】:

对于 WPF MediaElement,这是我使用的解决方案/解决方法:

bool IsPlaying()

    var pos1 = wpfMediaElement.Position;
    System.Threading.Thread.Sleep(1);
    var pos2 = wpfMediaElement.Position;

    return pos2 != pos1;

【讨论】:

那是可怕的解决方法。如果在 UI 线程中调用此方法,整个 UI 将被冻结。 我同意,这不是最好的方法。但我敢打赌,这个世界上没有人会在小程序上认出这一毫秒。这是亚历克斯的一种解决方法,我称之为快速'n脏,为此我将放弃投票。通过访问隐藏字段来使用隐藏的 HeperProperty 也确实不是一个“好的解决方案”。 没什么问题。没有状态属性的媒体元素是真正可怕的解决方案...也没有人要求你在 UI 线程中调用它。【参考方案8】:

对于 WPF 使用这个: var playing = player.Position < player.NaturalDuration;

【讨论】:

以上是关于如何确定 MediaElement 是不是正在播放?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 Dropbox 中的视频播放到我的 win phone 8 应用程序的 mediaelement 中?

如何判断 <video> 元素当前是不是正在播放?

如何通过 MediaElement 从库中播放文件?

ViewModel 中的 MediaElement.play()

播放后强制 MediaElement 释放流

从 NAudio 访问 WPF MediaElement 声音流