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

34

看起来很简单,但我找不到任何方法来确定MediaElement的状态。虽然有一些状态(如IsBuffering)的属性,但我找不到任何关于Play、Pause等状态的属性。Silverlight似乎有一个CurrentState属性可以显示所有这些状态。

目前,我确定视频是否应该播放的方式是观察各种事件和检查是否有任何进度的计时器。

我对MediaElement和WPF都很陌生(实际上我只是在一个WinForms应用程序中使用MediaElement)。我是否漏掉了什么?

9个回答

32

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


我已在WPF GitHub存储库中添加了一个关于此的功能请求。请前往并点赞。为MediaElement添加CurrentState属性#3655 - Jan Ivar Z. Carlsen

24

您可以使用反射访问_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()方法来解决此问题,这样可以正确更改状态(可以通过上面的方法检测到)。


2
优秀的解决方案!这就是正确的做法。 - Alex Pigida
3
除非微软在未来更改该字段的名称。 - George Birbilis
1
这对我来说完美地解决了问题。谢谢。我看到重命名可能存在的潜在危险,但我们还有什么其他解决方案呢?下面引用的“CurrentState”在现代完整的WPF中不存在。 - Michael Kennedy

9

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


6
把它放到CodePlex上。如果你没有时间,我打算这样做,只是不想得罪任何人。 - erodewald

4

对于 通用 Windows 10 平台 (UWP)

if ( yourMediaElement.CurrentState.ToString() == "Playing" ) 
{
    //nou yourMediaElement is playng
}

如果您想使用枚举,可以选择以下内容:
if (yourMediaElement.CurrentState == MediaElementState.Playing)
{
    //nou yourMediaElement is playng
}

2
基于 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;
        }
    }

2

对于 Silverlight,使用 CurrentState 来检查状态是否正在播放或暂停。

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

3
需要注意的是,CurrentState 只适用于 Silverlight。 - erodewald

0

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

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

    return pos2 != pos1;
}

10
这是一个可怕的解决方案。如果您在UI线程中调用此方法,整个UI将会被冻结。 - TcKs
1
我同意,这不是最好的方法。但我敢打赌,在小程序中没有人能够识别出这一毫秒。这是Alex的一个解决方法,我称之为快速而肮脏的方法,因此我会点赞。通过访问隐藏字段使用隐藏的HeperProperty确实不是一个“好的解决方案” 。 - Nasenbaer
媒体元素没有状态属性,这真是一个可怕的解决方案... 没有人要求你在UI线程中调用它。 - Boppity Bop

0
如果您使用 MediaElement.CanPause,它将确定当前正在播放的媒体是否可以暂停。这允许您实现播放/暂停按钮。
var media = (MediaElement)obj;
  if (media.CanPause)
  {
    media.Pause();
  }
  else
  {
    media.Play();
  }

-1

对于WPF使用以下代码:var playing = player.Position < player.NaturalDuration;


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接