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程序集中.
運行成功後, 你可以點擊歌曲名稱播放它, 進行測試.