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实现跳转到指定的状态。

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

 

 

阶段性的完结

你可能感兴趣的:(WPF)