Silverlight提供了MediaElement控件方便开发者制作音乐或媒体播放器, 它可以提供流畅的音乐播放和高清晰度的视频效果. 这里我们来介绍一下如何利用MediaElement控件制作简单的网页音乐播放器. 在这里示例中, 在网页中你可以看到一个MediaElement控件, 3个Slider控件, 一个DataGrid和若干个Button控件. MediaElement用于绑定音乐文件和播放, Slider控件用于绑定音乐的进度过程, 平衡度和音量, 你可以通过拖拽Slider来控制音乐文件的效果.
绑定平衡度和音量时比较简单的, 你可以直接通过Binding方法设置ElementName, path和UpdateSourceTrigger属性, 或者通过ValueChange事件来绑定. 对于进度条的绑定就稍微要麻烦一点, 一般我们有两种方式来实现, 第一个是采用Timer控件, 定期的去追踪音乐文件的播放事件, 并且改变Slider的Value值, 还有一种方式是通过创建一个继承IValueConvert接口的类返回Time的秒数, 绑定给Slider控件. 用户可以观察音乐的播放进度, 并且允许拖拽光标来实现快进或者倒退.
好了, 现在来看一下这个简单的媒体的播放器是怎么实现的, 首先, 确认一个你的电脑是够安装了Silverlight 4 SDK和SIlverlight 4 Toolkit. 运行Silverlight示例一般需要这两个基本程序, 它们的下载地址如下:
http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=7335
http://www.microsoft.com/download/en/details.aspx?id=18149
[本示例完整源码下载(0分)] http://download.csdn.net/source/3448102
基本准备工作结束了, 首先在Visual Studio里面创建一个Silverlight程序, 为了更贴近现在的开发环境, 在创建Silverlight程序时包括它寄宿的Web应用程序. 因为通常网络音乐播放器的音乐文件和播放列表是存在于Web服务器上的, 那么在默认存在的Web应用程序中的ClientBin文件夹中放入你的音乐文件(如a.mp3), 接着我们放入一个XML文件作为音乐播放列表, XML文件示例如下, 为了方便于测试, 这里我们只放进了两个音乐文件:
MusicList.xml
<root>
<music open="1" path="ClientBin/Mp3/Buddy Joe.mp3" name="Buddy Joe">Buddy Joe</music>
<music open="1" path="ClientBin/Mp3/Complicated.mp3" name="Complicated">Complicated</music>
</root>
接着, 在SIlverlight项目中创建一个DataItem实体类作为音乐文件的实体类, 包括音乐文件的名称和路径:
DataItem.cs
public class DataItem
{
private string nameItem;
private string pathItem;
public string NameItem
{
get
{
return nameItem;
}
set
{
nameItem = value;
}
}
public string PathItem
{
get
{
return pathItem;
}
set
{
pathItem = value;
}
}
}
创建一个类继承IValueConvert接口, 用于绑定Process Slider的控件值Value,使得用户能过观测到音乐文件的播放进度, 它必须实现两个方法Convert和ConvertBack:
ProgressConverter.cs
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);
}
}
接着修改MainPage.xaml文件, 添加必要的MediaElement, Slider, DataGrid等控件, DataGrid用于绑定XML文件的数据, 这里需要在XAML文件中引入ProcessConverter, 这需要在UserControl头文件中加入注册信息 xmlns:yw="clr-namespace:CSSL4MediaPlayer" 并且在Grid容器外引入UserControl的Resource文件 <UserControl.Resources> <yw:ProgressConverter x:Key="progress"></yw:ProgressConverter></UserControl.Resources> 全部代码如下:
MainPage.xaml
<UserControl xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
x:Class="CSSL4MediaPlayer.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:yw="clr-namespace:CSSL4MediaPlayer"
mc:Ignorable="d"
d:DesignHeight="478" d:DesignWidth="604">
<UserControl.Resources>
<yw:ProgressConverter x:Key="progress"></yw:ProgressConverter>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" HorizontalAlignment="Left" Width="599" Height="474" ShowGridLines="False" VerticalAlignment="Top" Margin="5,5,5,5">
<Grid.RowDefinitions>
<RowDefinition Height="68"/>
<RowDefinition Height="53"/>
<RowDefinition Height="71"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="282*" />
</Grid.RowDefinitions>
<MediaElement x:Name="mediaElement" Width="300" Grid.Row="1" AutoPlay="True"
IsMuted="False" Stretch="Fill" Volume="0.5"
CurrentStateChanged="mediaElement_CurrentStateChanged" MediaEnded="mediaElement_MediaEnded" MediaOpened="mediaElement_MediaOpened" Margin="44,0,44,147"></MediaElement>
<Button x:Name="btnStop" Content="stop" Grid.Row="2" Width="70" Height="25" Click="btnStop_Click" Margin="30,25,499,21"></Button>
<Button x:Name="btnPlay" Content="play" Grid.Row="2" Width="70" Height="25" Click="btnPlay_Click" Margin="0,25,430,21" HorizontalAlignment="Right"></Button>
<Button x:Name="btnPause" Content="pause" Grid.Row="2" Width="70" Height="25" Click="btnPause_Click" Margin="168,25,361,21"></Button>
<Button x:Name="btnMuted" Content="muted" Grid.Row="2" Width="70" Height="25" Click="btnMuted_Click" Margin="236,25,293,21"></Button>
<Button x:Name="btnFullScreen" Content="full screen" Grid.Row="2" Height="25" Click="btnFullScreen_Click" Margin="305,25,210,21"></Button>
<TextBlock Grid.Row="4" Height="23" HorizontalAlignment="Left" Margin="255,9,0,0" Name="textBlock1" Text="Music Play List" VerticalAlignment="Top" />
<sdk:DataGrid AutoGenerateColumns="False" ItemsSource="{Binding}" Grid.Row="4" Height="196" HorizontalAlignment="Left" Margin="196,36,0,50" Name="girdList" VerticalAlignment="Center" Width="206" SelectionChanged="girdList_SelectionChanged">
<sdk:DataGrid.Columns >
<sdk:DataGridTextColumn Header="name" Binding="{Binding NameItem}" Width="204" IsReadOnly="True"></sdk:DataGridTextColumn>
</sdk:DataGrid.Columns>
</sdk:DataGrid>
<TextBlock Height="34" Margin="200,18,197,0" Name="tbTitle" Text="Silverlight Media" VerticalAlignment="Top" FontSize="24" Width="200" />
<Slider x:Name="sliderProcess" Grid.Row="1" Minimum="0" Value="{Binding ElementName=mediaElement, Path=Position, Mode=TwoWay, Converter={StaticResource progress}}" Maximum="230" Margin="96,0,78,0" IsEnabled="False" />
<TextBlock Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="22,17,0,0" Name="textBlock2" Text="Process:" VerticalAlignment="Top" />
<Slider LargeChange="0.1" Margin="466,3,39,46" Maximum="1" SmallChange="0.01" Value="{Binding Volume, ElementName=mediaElement, Mode=TwoWay, UpdateSourceTrigger=Default}" Grid.Row="2" />
<TextBlock Height="23" HorizontalAlignment="Left" Margin="413,5,0,0" Name="tbTag1" Text="Volumn:" VerticalAlignment="Top" Grid.Row="2" />
<Slider LargeChange="0.1" Margin="466,43,39,6" Minimum="-1" Maximum="1" Grid.Row="2" ValueChanged="Slider_ValueChanged" Name="sliderBalance" />
<TextBlock Height="23" HorizontalAlignment="Left" Margin="413,45,0,0" Name="tbTag2" Text="Balance:" VerticalAlignment="Top" Grid.Row="2" />
<TextBlock Grid.Row="1" Height="16" HorizontalAlignment="Left" Margin="536,6,0,0" Name="tbTag" Text="Status:" VerticalAlignment="Top" />
<TextBlock Grid.Row="1" Height="19" HorizontalAlignment="Left" Margin="532,30,0,0" Name="tbStatus" Text="" VerticalAlignment="Top" />
</Grid>
</UserControl>
最后添加播放器的基本功能, 比如建立播放器的播放, 暂停, 停止, 静音, 全屏等功能, 实现异步的方法读取XML文件, 并且追踪MediaElement播放器的状态并且显示出来:
MainPage.xaml.cs
public partial class MainPage : UserControl
{
// Define some public properties of application, include data items,
// some signal variables, a TimeSpan class and a timer.
public List<DataItem> DataItems;
public bool blnIsMuted = false;
public bool blnIsFull = false;
private TimeSpan timeDuration;
public MainPage()
{
InitializeComponent();
this.XmlProcessMethod();
}
/// <summary>
/// This method used to asynchronous loading data from xml file and
/// adds DownLoadXmlComplete method with WebCient, it will add other
/// methods to timer and media element.
/// </summary>
private void XmlProcessMethod()
{
WebClient webClient = new WebClient();
webClient.DownloadStringAsync(new Uri(HtmlPage.Document.DocumentUri, "ClientBin/MusicList.xml"));
webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(this.DownLoadXmlComplete);
mediaElement.MediaEnded += new RoutedEventHandler(mediaElement_MediaEnded);
}
private void mediaElement_CurrentStateChanged(object sender, RoutedEventArgs e)
{
tbStatus.Text = mediaElement.CurrentState.ToString();
if (mediaElement.CurrentState != MediaElementState.Playing)
{
this.sliderProcess.IsEnabled = false;
}
else
{
this.sliderProcess.IsEnabled = true;
}
}
private void mediaElement_MediaEnded(object sender, RoutedEventArgs e)
{
tbStatus.Text = "complete";
mediaElement.Stop();
mediaElement.Position = TimeSpan.Zero;
}
private void mediaElement_MediaOpened(object sender, RoutedEventArgs e)
{
tbStatus.Text = "start";
// Retrieve music's total time.
timeDuration = mediaElement.NaturalDuration.HasTimeSpan ? mediaElement.NaturalDuration.TimeSpan : TimeSpan.FromMilliseconds(0);
sliderProcess.Maximum = timeDuration.TotalSeconds;
}
private void btnStop_Click(object sender, RoutedEventArgs e)
{
mediaElement.Pause();
mediaElement.Position = TimeSpan.Zero;
}
private void btnPlay_Click(object sender, RoutedEventArgs e)
{
mediaElement.Play();
}
private void btnPause_Click(object sender, RoutedEventArgs e)
{
mediaElement.Pause();
}
/// <summary>
/// Muted method
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnMuted_Click(object sender, RoutedEventArgs e)
{
if (!blnIsMuted)
{
btnMuted.Content = "Unmute";
mediaElement.IsMuted = true;
blnIsMuted = true;
}
else
{
btnMuted.Content = "Muted";
mediaElement.IsMuted = false;
blnIsMuted = false;
}
}
/// <summary>
/// Full screen method
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnFullScreen_Click(object sender, RoutedEventArgs e)
{
if (!blnIsFull)
{
btnFullScreen.Content = "Small Screen";
Application.Current.Host.Content.IsFullScreen = true;
blnIsFull = true;
}
else
{
btnFullScreen.Content = "Full Screen";
Application.Current.Host.Content.IsFullScreen = false;
blnIsFull = false;
}
}
/// <summary>
/// Load music data from xml file and convert data to a List of DataItem
/// instances. Bind DataGrid control's ItemSource with it.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void DownLoadXmlComplete(object sender, DownloadStringCompletedEventArgs e)
{
using (XmlReader reader = XmlReader.Create(new StringReader(e.Result)))
{
DataItems = new List<DataItem>();
while (reader.Read())
{
if (reader.IsStartElement() && reader.GetAttribute("open") == "1")
{
string pathMusic = reader.GetAttribute("path").ToString();
string nameMusic = reader.GetAttribute("name").ToString();
DataItem dataItem = new DataItem();
dataItem.NameItem = nameMusic;
dataItem.PathItem = pathMusic;
DataItems.Add(dataItem);
}
}
this.DataContext = DataItems;
}
}
/// <summary>
/// Allow user to change another song.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void girdList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
sliderProcess.IsEnabled = true;
mediaElement.Position = new TimeSpan(0);
sliderProcess.Value = 0;
DataItem selectItem = (DataItem)girdList.SelectedItem;
mediaElement.Source = new Uri(HtmlPage.Document.DocumentUri, selectItem.PathItem);
mediaElement.Play();
}
/// <summary>
/// Go back to the beginning of slider control when music plays complete
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void mdeMusic_MediaEnded(object sender, RoutedEventArgs e)
{
sliderProcess.Value = 0;
}
/// <summary>
/// Balance slider
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
mediaElement.Balance = sliderBalance.Value;
}
}
那么这个简单的播放器算是制作完成的, 你需要设置Silverlight.Web应用程序为启动项(注意不是Silverlight), 如果你从Silverlight程序进入, 那么你会在加载Xml文件时收到一个TargetInvocationException错误, 这是因为你的Silverlight无法读取Web应用程序中的xml导致的, 你当然也可以把XML文件置于Silverlight程序集中.
运行成功后, 你可以点击歌曲名称播放它, 进行测试.