惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hugging Face - Blog
Hugging Face - Blog
云风的 BLOG
云风的 BLOG
大猫的无限游戏
大猫的无限游戏
M
MIT News - Artificial intelligence
L
LangChain Blog
阮一峰的网络日志
阮一峰的网络日志
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Recent Announcements
Recent Announcements
IT之家
IT之家
Google DeepMind News
Google DeepMind News
罗磊的独立博客
爱范儿
爱范儿
Last Week in AI
Last Week in AI
人人都是产品经理
人人都是产品经理
U
Unit 42
MongoDB | Blog
MongoDB | Blog
S
SegmentFault 最新的问题
B
Blog
博客园 - 叶小钗
月光博客
月光博客
Stack Overflow Blog
Stack Overflow Blog
V
Visual Studio Blog
C
Check Point Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知

博客园 - Saar

LightSwitch 2011 实践之个人汽车仓库 —— 起步 让我们更快一点的Visual Studio的技巧们 实战 WPF Jump List 编程 实战Bing MAP REST服务的封装、调用 选好 Async 函数的返回类型 用WCF + Entity Framework 序列化时的陷阱 大家都来搭架构 —— VS 2010 Layer Diagram (层图) 基本使用 基于Entity Framework 4.1实现一个适用于单元测试的MockDbContext(下) 基于Entity Framework 4.1实现一个适用于测试的MockDbContext(上) 利用IProgress轻松搞定进度条编程 C# 5.0功能之Async一瞥 C#不是C++ 之 委托(Delegate) C#不是C++ 之 泛型(Generic) Silverlight 学习笔记——MVVM模式实现主从数据显示 Silverlight 学习笔记——应用程序模型 Visual Studio 2010 部分新功能概览-QS, HR, GFU Silverlight学习笔记——依赖属性和路由事件 Silverlight 学习笔记——布局 Visual Studio 2010 部分新功能概览-Dynamic & Named / Optional Parameters
Silverlight 学习笔记——用MediaElement制作在线音乐播放器
Saar · 2010-01-15 · via 博客园 - Saar

  Silverlight的一个很大的特性就是针对多媒体内容,包括音频和视频的支持。在Silverlight中,多媒体内容通过窗口MediaElement来呈现。让我们通过实现一个在线音乐播放器,来学习MediaElement对于音频的支持特性。

  首先通过Blend Sketch来打个草稿,规划一下最终要实现的界面和功能:

MusicPlayer001

  • 播放器功能:

  • 大进度条,用于追踪歌曲的播放进度,并且可以通过拖放来定位到歌曲的不同位置;
  • Start按钮,开始播放;按钮变成Pause,用于暂停;(实现时,改为了Play按钮);
  • Stop按钮,停止播放;
  • Mute按钮,静音;
  • Volume和Balance两个滑条分别控制音量和左右平衡。

  MediaElement类中提供的方法、属性和事件,可以为我们实现以上全部的功能:

方法:

  Play

  从媒体当前位置开始播放。这个方法可以实现Start按钮播放部分的功能;

  Pause

  将媒体暂停在当前位置。当用户按下播放以后,播放按钮就会变成暂停按钮,当用户点击暂停按钮就,调用此方法将正在播放的歌曲停住。

  Stop

  将媒体停止并且重置至起始位置。正好对应了Stop按钮的功能。

属性:

  AutoPlay,bool类型

  设置或者获取添加完Source时,是否自动播放。由于我们期望用户点击Start按钮时才进行播放,因此,这处需要将其设置为false。

  Balance,double类型

  设置或者获取扬声器平衡。数值区间:-1~1。用于绑定Balance滑块。

  IsMute,bool类型

  设置或者获取是否静音,我们通过Mute按钮设置其值。

  Position,TimeSpan类型。

  通过时间设置或者获取播放中媒体当前的位置。歌曲进度可以通过获取MeidaElement.Position属性中的TotalSeconds来实现,这里有一个小技巧,设置时,可以通过TimeSpan.FromSeconds方法来进行。由于Position是TimeSpan类型的,而滑动条的Value是double值,因此,在绑定的时候,需要引入一个转换器Converter。这将在后面的代码中有所体现。

  Source,System.Uri类型

  提供媒体源。指向要播放的音乐文件或者播放列表。

  Volume,double类型

  设置或者获取音量。用于绑定到Volume滑块。

事件:

  MediaFailed

  设置Source失败时触发。为了简化,这里使用了一个固定的文件,因此,也没有考虑载入失败的问题。这个事件也没有被用到。另外,如果Source指向一个无效的路径,默认情况下,Silverlight会触发这个事件但是不会抛出异常。因此,如果载入文件失败时需要抛出异常,我们需要手动的在MediaFailed事件处理程序中创建并抛出异常。

  MediaEnded

  媒体播放完成时触发。当一首歌曲播放完成时,需要将界面复原,例如,将Pause按钮还原为Start按钮。

  • 实战

  好,理论知识准备完毕,让我们开始制作。首先,绘制一个5行3列的Grid。

  MusicPlayer002

  为了固定播放器的大小,只有最后一行和最后一列没有锁定宽和高。第四行添加了一个方向为水平的StackPanel,并且添加了各个按钮。界面完成以后,用Visual Studio打开项目,双击Play按钮,添加事件处理程序:

        private void btnStart_Click(object sender, RoutedEventArgs e)
{
Button self = sender as Button;
if (self.Content.ToString().ToUpper() == "PLAY")
{
sldProgress.Maximum = mdeMusic.NaturalDuration.TimeSpan.TotalSeconds;
self.Content = "Pause";
mdeMusic.Play();
}
else
{
mdeMusic.Pause();
self.Content = "Play";
}
}

  这里,我们通过判断按钮的Content是否为“Play”来判断当前按钮的功能。当为“Play”时,我们为大的进度滑块设置最大值——整个音乐的全部秒数,然后把按钮上的文字改成“Pause”,并开始播放音乐。而当按钮上的文字不为“Play”时,调用Pause方法将播放暂停,并且再次把按钮上的文字改成“Play”。

  Stop按钮的功能很直接,把“Play”按钮上的字改为“Play”,并且调用MediaElement的Stop方法将播放停止。

  Mute按钮其实相当于一个CheckBox,或者一个乒乓键,因此,每次点击,我们只需要将逻辑值置返即可:

        private void btnMute_Click(object sender, RoutedEventArgs e)
{
mdeMusic.IsMuted = !mdeMusic.IsMuted;
}

  Volume的滑块只需要设置其最大值为1并且绑定即可:

<Slider x:Name="sldVolumn" Style="{StaticResource SliderPlayers}" Value="{Binding Volume, ElementName=mdeMusic, Mode=TwoWay, UpdateSourceTrigger=Default}" Maximum="1" LargeChange="0.1" SmallChange="0.01" />

  Blalance滑块依样画瓢,不再赘述。

  最后,我们要把Position绑定到进度滑块上。做个简单的分析,这里,MediaElement的Position相当于模型,而Slider的Value即是控件上需要绑定的值。当从模型向控件绑定时,我们需要从TimeSpan中提取出总的秒数,提供给滑快的Value。而从控件到模型时,又需要把Value这个double类型的数值,设置成Position当前的秒数。因此,正向时,需要把TimeSpan转换成double,反向时则反过来。由此,便可以实现IValueConverter接口了:

    public class ProgressConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return ((TimeSpan)value).TotalSeconds;
}

public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return TimeSpan.FromSeconds((double)value);
}
}

  其中,Convert实现正向转换;ConvertBack则实现逆向的转换。有了转换器,我们便可以把MediaElement的Position和进度滑块绑定起来了:

<Slider x:Name="sldProgress" Grid.Column="1" Grid.Row="2" Minimum="0" Value="{Binding ElementName=mdeMusic, Path=Position, Mode=TwoWay, Converter={StaticResource PrgConverter}}" LargeChange="10" />

  让我们运行项目,效果如下:

MusicPlayer003

  一曲放完,我们发现,Play按钮没有返回到原来的状态,仍然是Pause,这显然不是我们想要的效果,因此,我们还需要做些手脚。首先,在MainPage的构造函数中添加MediaElement的MediaEnded事件的处理程序:

        public MainPage()
{
// Required to initialize variables
InitializeComponent();
tbMusicName.Text = "Guo Qiao";
mdeMusic.MediaEnded += new RoutedEventHandler(mdeMusic_MediaEnded);
}

  然后,在事件处理程序中,将播放按钮复原:

        void mdeMusic_MediaEnded(object sender, RoutedEventArgs e)
{
btnStart.Content = "Play";
sldProgress.Value = 0;
}
  • 写在最后:

  Silverlight通过MediaElement类为多媒体支持,通过其内置的方法、属性和事件,基本上可以完成一个在线音乐播放器的所有功能。可惜Silverlight不能访问本地文件,否则,做一个Web版的本地播放器也是一件很Cool的事情:-)。

Little knowledge is dangerous.