WPF开发较为完整的音乐播放器(三) ---数据读取类以及界面的构建和所有代码

 

 

    先向大家阐述下,由于我装的Windows8系统不含WMP,因此不能再继续正常开发下去了,我会将我已经写好的悉数公开来,并且在最后给个后边的思路,大家可以修改代码继续写下去,并且可以在评论中交流。

先附上之前的xml样本:

<?xml version="1.0" encoding="utf-8" ?>
<MusicList name="{Name}">
  <Music url="{URl}" singer="{singer}">{title}</Music>
  <Music url="{URl}" singer="{singer}">{title}</Music>
</MusicList>

 

 

    废话不多说,继续写。

     数据读取类用来和ListBox绑定,这里由于是依赖项属性,可以用更改通知,但是笔者并没有使用,而是使用笨拙的DispatcherTimer,大家可以尝试下更简洁的数据更改通知。

    由于类是比较简单的,直接上代码:

    public class XmlListProduct
    {
        public XmlListProduct(string url,string name,string singer)
        {
            Url = url;
            Title = name;
            Singer = singer;       
        }

        
        public string Url
        { get; set; }
        public string Title
        { get; set; }
        public string Singer
        { get; set; }
    }

其中属性依次是音乐文件地址,音乐名,歌手名,(别问我为什么没有持续时间,我倒是想加)。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WpfApplication10
{
    public class Product
    {
        public Product(TimeSpan musicposition)
        {
            MusicPosition = musicposition;
        }
public TimeSpan MusicPosition
        {
            set;
            get;
        }
    }

}

这一部分则是绑定播放器的播放时间,实现播放控制Slider移动,C#代码鉴下边的主界面代码。

此前说过工程中列表和播放控制是两个控件,就先发下播放控制的xaml:

<UserControl x:Class="WpfApplication10.PlayControls"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WpfApplication10"
             mc:Ignorable="d" 
             d:DesignHeight="100" d:DesignWidth="300">
    <UserControl.Resources>
        <local:MusicTimeConverter x:Key="musictimeconverter"></local:MusicTimeConverter>
        <local:TimeSpanConverter x:Key="dateconverter"></local:TimeSpanConverter>
        <local:SecondsConverter x:Key="secondsconverter"></local:SecondsConverter>
    </UserControl.Resources>
    <Grid>
          <Grid.RowDefinitions>
              <RowDefinition></RowDefinition>
              <RowDefinition></RowDefinition>
              <RowDefinition></RowDefinition>
          </Grid.RowDefinitions>
        <TextBlock Name="musictitle"></TextBlock>
        <Grid Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="8*"></ColumnDefinition>
                <ColumnDefinition Width="2*"></ColumnDefinition>
            </Grid.ColumnDefinitions>
           <Slider  Name="timecontrol" Focusable="False" FocusVisualStyle="{x:Null}"
  VerticalAlignment="Center" Margin="5" Value="{Binding MusicPosition,Converter={StaticResource secondsconverter}}"/>
            <TextBlock Grid.Column="1" VerticalAlignment="Center" Margin="5" Text="{Binding MusicPosition,Converter={ StaticResource dateconverter}}"></TextBlock>
        </Grid>
        <Grid Grid.Row="2">
            <Grid.ColumnDefinitions>
                <ColumnDefinition></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <Button Grid.Column="0" Content="上一曲" Name="lastKey"></Button>
            <Button Grid.Column="1" Content="播放" Name="playKey">
            </Button>
            <Button Grid.Column="2" Content="下一曲" Name="nextKey"></Button>
            <Slider Grid.Column="4" Maximum="100" Name="volume"></Slider>
        </Grid>
    </Grid>
</UserControl>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication10
{
    /// <summary>
    /// PlayControls.xaml 的交互逻辑
    /// </summary>
    public partial class PlayControls : UserControl
    {


        public PlayControls()
        {
            InitializeComponent();
            this.Loaded += PlayControls_Loaded;

        } 
       
        void PlayControls_Loaded(object sender, RoutedEventArgs e)
        {
            
        }
        /// <summary>
        /// 设置播放控制区 的标题
        /// </summary>
        /// <param name="title"></param>
       public void SetTitle(string title)
        {
            musictitle.Text = title;
        }
        /// <summary>
        /// 设置播放控制Slider的最大值
        /// </summary>
        /// <param name="num"></param>
       public  void SetMaxNum(double num)
        {
            timecontrol.Maximum = num;
        }
    }
}

 

 

列表文件的xaml:

<UserControl x:Class="WpfApplication10.PlayLists"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
<ListBox  Name="list"  Focusable="False" Width="300" Padding="0"  Style="{StaticResource listStyle}" HorizontalAlignment="Stretch"  MouseDoubleClick="item_MouseDoubleClick">
    </Grid>
</UserControl>

c#code:

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication10
{
    /// <summary>
    /// PlayLists.xaml 的交互逻辑
    /// </summary>
    public partial class PlayLists : UserControl
    {

        public PlayLists()
        {
            InitializeComponent();
            InitList();
        }

        private void InitList()
        {
            List<XmlListProduct> musiclist = new List<XmlListProduct>();
            MusicListsReader mlr = new MusicListsReader("PlayLists.xml");  //加载播放列表的文件
            for (int i = 0; i < mlr.GetXmlCount(); i++)
            {
              
               XmlListProduct xlp= mlr.GetXmlMusicItemInformation(i);  //读取xml中的信息
               ListBoxItem item = new ListBoxItem();
               item.Content= xlp;

               musiclist.Add(xlp);
               
            }
            list.ItemsSource = musiclist;   //绑定到ItemSource
        }

    }
}

 

在其中还用到了值转换器:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WpfApplication10
{
    public class TimeSpanConverter:System.Windows.Data.IValueConverter
    {

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            TimeSpan ts = (TimeSpan)value;
            string result = String.Format("{0:mm\\:ss}", ts);
            return result;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return value;
        }
    }
    public class SecondsConverter : System.Windows.Data.IValueConverter
    {

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            TimeSpan ts = (TimeSpan)value;
            double seconds = ts.TotalSeconds;
            return seconds;
        }

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

}

 

主界面的xaml:

 

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication10" x:Class="WpfApplication10.MainWindow"
        Title="音乐播放器" Height="400" Width="300">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <TextBlock><Run Text="音乐播放器"/></TextBlock>

        <local:PlayControls x:Name="playcontrols"  HorizontalAlignment="Stretch"  Grid.Row="1" VerticalAlignment="Center" Loaded="PlayControls_Loaded_1"/>
        <local:PlayLists x:Name="playlists" HorizontalAlignment="Stretch"  Grid.Row="2" VerticalAlignment="Stretch"/>
    </Grid>
</Window>

主界面的code:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using WpfApplication10;
namespace WpfApplication10
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MusicPlay play = null;
        public string nowTitle;
        public int count=0;
        public MainWindow()
        {
            InitializeComponent();
            play = new MusicPlay();
        }
       static MainWindow()
       {

       }
        private void PlayControls_Loaded_1(object sender, RoutedEventArgs e)
        {
            playcontrols.playKey.Click += playKey_Click;
            playcontrols.nextKey.Click += nextKey_Click;
            playcontrols.lastKey.Click += lastKey_Click;
            playcontrols.volume.Loaded += volume_Loaded;
            playcontrols.volume.ValueChanged += volume_ValueChanged;
            AddHandler(System.Windows.Controls.Primitives.Thumb.DragStartedEvent, new DragStartedEventHandler(DragStarted));
            AddHandler(System.Windows.Controls.Primitives.Thumb.DragCompletedEvent, new DragCompletedEventHandler(DragCompleted));
            play.dt = new System.Windows.Threading.DispatcherTimer();
            play.dt.Interval = TimeSpan.FromSeconds(1);
            play.dt.Tick += dt_Tick;
        }

        void volume_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            play.SetVolume(e.NewValue);
        }

        void volume_Loaded(object sender, RoutedEventArgs e)
        {
            playcontrols.volume.Value = play.GetVolume();
        }

        private void ThumbMouseClick(object sender, MouseEventArgs e)
        {
            
        }
        private void DragCompleted(object sender, DragCompletedEventArgs e)
        {
            TimeSpan ts = TimeSpan.FromSeconds(playcontrols.timecontrol.Value);
            Debug.WriteLine(ts);
            play.SetPosition(ts);
            Product product = new Product(ts);
            playcontrols.DataContext = product;
            play.dt.Start();
        }
        /// <summary>
        /// 音乐控制滑块开始拖动事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DragStarted(object sender, DragStartedEventArgs e)
        {
            play.dt.Stop();
            if (count == 0)
            {
                playcontrols.timecontrol.ClearValue(Slider.ValueProperty);
                count++;
            }
        }
        /// <summary>
        /// 播放上一曲音乐
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void lastKey_Click(object sender, RoutedEventArgs e)
        {
            ischange = true;
            //如果上一曲存在
            if (playlists.list.SelectedIndex >= 1)
            {
                playlists.list.SelectedIndex = playlists.list.SelectedIndex - 1;//选中上一个音乐

                PlayMusic(0);//播放选择的音乐
            }
        }    

        void nextKey_Click(object sender, RoutedEventArgs e)
        {
            ischange = true;
            //如果下一曲存在
            if (playlists.list.SelectedIndex < playlists.list.Items.Count)
            {
                playlists.list.SelectedIndex = playlists.list.SelectedIndex + 1;//选中下一曲音乐
                PlayMusic(0);//播放选中的音乐
            }
        }
        /// <summary>
        /// 播放列表中选中的音乐
        /// </summary>
        void PlayMusic(int type)
        {
            if (type == 0)
            {
                XmlListProduct item = (XmlListProduct)playlists.list.SelectedItem;
                
                play.Load(new Uri(item.Url));

                nowTitle = item.Title + "--" + item.Singer;

                Product p = new Product(play.GetPosition());
                playcontrols.SetTitle(nowTitle);
                play.Play();
                playcontrols.SetMaxNum(play.GetMusicDuringTime().TotalSeconds);
                playcontrols.DataContext = p;
                System.Threading.Thread.Sleep(100);
            }
            
            play.Play();
        }
        //播放/暂停按钮
        void playKey_Click(object sender, RoutedEventArgs e)
        {
            
    
                if (ischange)
                {
                    if (play.GetPlayState() == MusicPlay.PlayState.playing)
                    {
                        play.Pause();
                        playcontrols.playKey.Content = "播放";
                    }
                    else
                    {
                        PlayMusic(1);
                        playcontrols.playKey.Content = "暂停";
                    }

                }
                else
                {
                    if (playlists.list.SelectedIndex < 0)
                    {
                        playlists.list.SelectedIndex = 0;
                    }
                    PlayMusic(0);
                    playcontrols.playKey.Content = "暂停";

                }
                ischange = true;
            

        }

        void dt_Tick(object sender, EventArgs e)
        {
            if (play.GetPlayState() == MusicPlay.PlayState.playing)
            {
                Product product=new Product(play.GetPosition());
                playcontrols.DataContext = product;
                    
            }
        }

        public bool ischange=false;
    }
}

 值得提醒的是

            AddHandler(System.Windows.Controls.Primitives.Thumb.DragStartedEvent, new DragStartedEventHandler(DragStarted));
            AddHandler(System.Windows.Controls.Primitives.Thumb.DragCompletedEvent,
new DragCompletedEventHandler(DragCompleted));

 

 这两段代码实现了关联Slider的滑块拖动事件,前者是开始拖动,后者是完成拖动,其余代码大家看下。

还有就是空间模板和数据模板,没学过的可以百度下:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:WpfApplication10">
   
     <Style TargetType="{x:Type ListBox}" x:Key="listStyle">
        <Style.Setters>
            <Setter Property="ListBox.ItemTemplate">
                <Setter.Value>
                    <DataTemplate DataType="ListBox">
                         <Grid Margin="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="250">
                            <Grid.RowDefinitions>
                                <RowDefinition></RowDefinition>
                                <RowDefinition></RowDefinition>
                            </Grid.RowDefinitions>

                             <Grid Grid.Row="0">
                                 <Grid.ColumnDefinitions>
                                     <ColumnDefinition></ColumnDefinition>
                                     <ColumnDefinition></ColumnDefinition>
                                 </Grid.ColumnDefinitions>
                                <TextBlock HorizontalAlignment="Left" Text="{Binding Title}" Grid.Column="0"></TextBlock>
                                 <TextBlock HorizontalAlignment="Right" Text="45242" Grid.Column="1"></TextBlock>
                             </Grid>
                             <Grid Grid.Row="1" Margin="0">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition></ColumnDefinition>
                                    <ColumnDefinition></ColumnDefinition>
                                </Grid.ColumnDefinitions>
                                 <TextBlock HorizontalAlignment="Left" Text="{Binding Singer}" Name="singer"></TextBlock>
                             </Grid>
                        </Grid>
                    </DataTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="Background" Value="#FFF4F9EF"></Setter>
        </Style.Setters>
    </Style>
    <Style TargetType="{x:Type ListBoxItem}">
        <Style.Setters>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ListBoxItem}">

                        <Border Background="{TemplateBinding Background}" Name="root">
                           
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup Name="fgfg">
                                    <VisualStateGroup.Transitions>
                                        <VisualTransition From="Normal" To="MouseOver" GeneratedDuration="0:00:0.1"></VisualTransition>
                                    </VisualStateGroup.Transitions>
                                    <VisualState x:Name="Normal"></VisualState>

                                    <VisualState x:Name="MouseOver">
                                        <Storyboard>
                                            <ColorAnimation Storyboard.TargetName="root"  Storyboard.TargetProperty="Background.Color" To="#FFDEEDCE"></ColorAnimation>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="Selected">
                                        <Storyboard>
                                            <ColorAnimation Storyboard.TargetName="root" Storyboard.TargetProperty="Background.Color" To="#FFCDE3B4"></ColorAnimation>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="MouseDouble">
                                        <Storyboard>
                                            <ColorAnimation Storyboard.TargetName="root" Storyboard.TargetProperty="Background.Color" To="#FF9BC669"></ColorAnimation>
                                        </Storyboard>
                                    </VisualState>

                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>

                            <ContentPresenter Content="{TemplateBinding ContentControl.Content}"
                                              HorizontalAlignment="{TemplateBinding ContentControl.HorizontalAlignment}"
                                              VerticalAlignment="{TemplateBinding ContentControl.VerticalAlignment }"
                                              ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}"
                                              SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}"/>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
       </Style.Setters>
    </Style>

</ResourceDictionary>


VisualStateManager实现了空间状态外观的快速切换,可用VisualStateManager.GoToState实现跳转到指定的状态。

再次提醒大家,代码仅仅是给大家作参考的,如果有时间,我会做出一个完整版的给大家展示。

 

 

阶段性的完结

posted @ 2012-08-07 18:57  deepwzh  阅读(5763)  评论(5编辑  收藏  举报