程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> WPF中使用MediaElement控件來進行音視頻播放

WPF中使用MediaElement控件來進行音視頻播放

編輯:關於.NET

WPF中可以使用MediaElement控件來進行音視頻播放,然後需要做個進度條啥的,但是MediaElement.Position(進度)和MediaElement.NaturalDuration居然都不是依賴屬性,簡直不能忍!

好吧,首先說說比較傳統的做法(winform?)

slider用來顯示進度以及調整進度,tb1顯示當前進度的時間值,tb2顯示視頻的時長。

player_Loaded 事件中使用DispatcherTimer來定時獲取當前視頻的播放進度,

player_MediaOpened 事件中獲取當前視頻的時長(只有在視頻加載完成後才可以獲取到)

slider_ValueChanged 事件中執行對視頻進度的調整

xaml:  
<MediaElement Name="player" Source="e:\MVVMLight (1).wmv" Loaded="player_Loaded"
                      MediaOpened="player_MediaOpened" />  
        <Slider Grid.Row="1"  Margin="10" Name="slider" ValueChanged="slider_ValueChanged" />  
        <WrapPanel Grid.Row="1"  Margin="0,40,0,0">  
            <TextBlock Name="tb1" Width="120" />  
            <TextBlock Name="tb2" Width="120" />  
        </WrapPanel>  
      
後台代碼:  
private void player_Loaded(object sender, RoutedEventArgs e)  
        {  
            DispatcherTimer timer = new DispatcherTimer();  
            timer.Interval = TimeSpan.FromMilliseconds(1000);  
            timer.Tick += (ss, ee) =>  
            {  
                //顯示當前視頻進度  
                var ts = player.Position;  
                tb1.Text = string.Format("{0:00}:{1:00}:{2:00}", ts.Hours, ts.Minutes, ts.Seconds);slider.Value = ts.TotalMilliseconds;  
            };  
            timer.Start();  
        }  
      
        private void player_MediaOpened(object sender, RoutedEventArgs e)  
        {  
            //顯示視頻的時長  
            var ts = player.NaturalDuration.TimeSpan;  
            tb2.Text = string.Format("{0:00}:{1:00}:{2:00}", ts.Hours, ts.Minutes, ts.Seconds);  
            slider.Maximum = ts.TotalMilliseconds;  
        }  
      
        private void slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)  
        {  
            //調整視頻進度  
            var ts = TimeSpan.FromMilliseconds(e.NewValue);  
            player.Position = ts;  
        }

本欄目

下面再來看看使用依賴屬性的做法:

添加一個類,繼承MediaElement

public class MediaElementExt : MediaElement, INotifyPropertyChanged  
    {  
        private DispatcherTimer timer;  
      
        private const string CurrentTimeProperty = "CurrentTime";  
      
        /// <summary>  
        /// 當前播放進度  
        /// </summary>  
        public double CurrentTime  
        {  
            get
            {  
                return this.Position.TotalMilliseconds;  
            }  
            set
            {  
                //進度條拖動太頻繁太久,性能跟不上,所以設置一個時間閥,跳過某些時段  
                if ((DateTime.Now - _lastChangedTime).TotalMilliseconds > 50)  
                {  
                    this.Position = TimeSpan.FromMilliseconds(value);  
                    _lastChangedTime = DateTime.Now;  
                }  
            }  
        }  
      
        /// <summary>  
        /// 記錄最後修改進度的時間,  
        /// </summary>  
        private DateTime _lastChangedTime = DateTime.Now;  
      
        private const string DurationTimeProperty = "DurationTime";  
      
        /// <summary>  
        /// 當前視頻時長  
        /// </summary>  
        public double DurationTime  
        {  
            get
            {  
                if (this.NaturalDuration.HasTimeSpan)  
                    return this.NaturalDuration.TimeSpan.TotalMilliseconds;  
                return double.NaN;  
            }  
        }  
      
        public MediaElementExt()  
        {  
            timer = new DispatcherTimer();  
            timer.Interval = TimeSpan.FromMilliseconds(1000);  
            timer.Tick += timer_Tick;  
      
            this.MediaOpened += (ss, ee) =>  
             {  
                 //觸發PropertyChanged DurationTime  
                 this.RaisePropertyChanged(DurationTimeProperty);  
                 timer.Start();  
             };  
            //發生錯誤和視頻播放完畢 停止計時器  
            this.MediaEnded += (ss, ee) => { timer.Stop(); };  
            this.MediaFailed += (ss, ee) => { timer.Stop(); };  
        }  
      
        void timer_Tick(object sender, EventArgs e)  
        {  
            //定時觸發PropertyChanged CurrentTime  
            this.RaisePropertyChanged(CurrentTimeProperty);  
        }  
      
        public event PropertyChangedEventHandler PropertyChanged;  
      
        public void RaisePropertyChanged(string propertyName)  
        {  
            if (this.PropertyChanged != null)  
            {  
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));  
            }  
        }  
    }
<Grid DataContext="{Binding ElementName=player}">  
        <Grid.RowDefinitions>  
            <RowDefinition Height="8*" />  
            <RowDefinition Height="2*" />  
        </Grid.RowDefinitions>  
        <!--<MediaElement />-->  
        <local:MediaElementExt  x:Name="player" Source="e:\MVVMLight (1).wmv"  />  
        <Slider Name="slider" Grid.Row="1" Value="{Binding CurrentTime,Mode=TwoWay}"  Maximum="{Binding DurationTime,Mode=OneWay}" Margin="10" />  
        <WrapPanel Grid.Row="1"  Margin="0,40,0,0">  
            <TextBlock Text="{Binding Value, Converter={StaticResource TimeSpanConverter}, Mode=OneWay,ElementName=slider}" Width="120" />  
            <TextBlock Text="{Binding DurationTime, Mode=OneWay,Converter={StaticResource TimeSpanConverter}}" Width="120" />  
        </WrapPanel>  
    </Grid>  
      
---  xmlns:local="clr-namespace:WPF_Player"
public class TimeSpanConverter : IValueConverter  
    {  
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)  
        {  
      
            var ts = TimeSpan.FromMilliseconds((double)value);  
            return string.Format("{0:00}:{1:00}:{2:00}", ts.Hours, ts.Minutes, ts.Seconds);  
        }  
      
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)  
        {  
            throw new NotImplementedException();  
        }  
    }

xaml中的轉換器:

<local:TimeSpanConverter x:Key="TimeSpanConverter" />

其實兩種方法實現的都差不多,都需要計時器定時的去獲取當前視頻的進度,但第二種方面顯然要優雅一些。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved