媒体元素和进度栏Windows手机

时间:2012-12-31 06:26:36

标签: c# windows-phone-7 xaml windows-phone-8 mediaelement

我想播放声音,并在每个声音下方显示进度条 我正在VM中显示当前的进度:(来源:http://dotnet.dzone.com/articles/playing-media-content-windows

player.CurrentStateChanged += player_CurrentStateChanged;
[...]
 void player_CurrentStateChanged(object sender, RoutedEventArgs e)
    {
        var mediaPlayer = sender as MediaElement;
        if (mediaPlayer != null && mediaPlayer.CurrentState == MediaElementState.Playing)
        {
            var duration = mediaPlayer.NaturalDuration.TimeSpan.TotalSeconds;
            ThreadingHelper.ExecuteAsyncAction(() =>
                {
                    do
                    {
                        ThreadingHelper.ExecuteOnUiThread(() =>
                        {
                            Progress = mediaPlayer.Position.TotalSeconds * 100 / duration;
                        });
                        Thread.Sleep(10);
                    } while (IsPlaying);
                });
        }
    }

和xaml:

<!--TITLE-->
                <TextBlock Text="{Binding Sound.Libelle}"
                           Style="{StaticResource PhoneTextNormalStyle}"
                           TextWrapping="Wrap"/>

            <ProgressBar Height="20" Width="400" Value="{Binding Progress}"></ProgressBar>

进度条显示正确,问题是当我播放第二个声音时,由于与我的Progress属性绑定,第一个进度条也会更新。

我不知道如何防止这种行为,欢迎任何想法。

编辑:我忘了提到只有当我在第一个播放时开始播放另一个声音时才会出现这种情况。我的第一个声音停止,第二个开始,但两个进度条都更新

EDIT2:多一点代码:

 private void PlaySong()
    {
        MediaElement player = null; // get the media element from App resources
        if (Application.Current.Resources.Contains("MediaPlayer"))
        {
            player = Application.Current.Resources["MediaPlayer"] as MediaElement;
        }
        if (player != null)
        {
            if (IsPlaying)
            {
                player.Stop();
                player.MediaEnded -= player_MediaEnded;
                player.CurrentStateChanged -= player_CurrentStateChanged;
            }
            else
            {
                player.Source = new Uri(Sound.Link, UriKind.Relative);
                player.Play();
                player.MediaEnded += (o, args) => player_MediaEnded(player, args);
                player.CurrentStateChanged += player_CurrentStateChanged;
                IsPlaying = true;
            }
        }            
    }

这是名为PlaySong()的{​​{1}}方法,它获取了我的app.xaml中定义的唯一onClick。它根据当前的声音状态播放或停止。

这是我的xaml,它是绑定到SoundViewModel的ObservableCollection的MediaPlayer控件的模板

<ListBox>

所以应用程序中有一个ProgressBar / Sound和一个<Button x:Name="SoundButton" Command="{Binding PlaySongCommand}" HorizontalAlignment="Stretch" Style="{StaticResource EmptyButtonStyle}"> <StackPanel Margin="12,0,0,12"> <!--TITLE--> <TextBlock Text="{Binding Sound.Libelle}" Style="{StaticResource PhoneTextNormalStyle}" TextWrapping="Wrap"/> <ProgressBar Height="20" Width="400" Value="{Binding Progress}"></ProgressBar> </StackPanel> <!-- LONG HOLD GESTION--> <toolkit:ContextMenuService.ContextMenu> <toolkit:ContextMenu Name="AllsoundMenu" IsZoomEnabled="True"> <toolkit:MenuItem Header="Add to favorite" Command="{Binding AddToFavoriteCommand}" /> <toolkit:MenuItem Header="Add as a ringtone" Command="{Binding AddToRingtoneCommand}" /> </toolkit:ContextMenu> </toolkit:ContextMenuService.ContextMenu> </Button> 。 希望这有助于你看清楚。

也许我不会只有一个MediaElement,但实现这种方式似乎是正确的。

1 个答案:

答案 0 :(得分:0)

我认为你应该尝试在声音未运行时从'player'对象中删除处理程序。我希望它会有所帮助。像这样:

 void player_CurrentStateChanged(object sender, RoutedEventArgs e)
    {
        var mediaPlayer = sender as MediaElement;
        if (mediaPlayer != null && mediaPlayer.CurrentState == MediaElementState.Playing)
        {
            var duration = mediaPlayer.NaturalDuration.TimeSpan.TotalSeconds;
            ThreadingHelper.ExecuteAsyncAction(() =>
                {
                    do
                    {
                        ThreadingHelper.ExecuteOnUiThread(() =>
                        {
                            //A list of values , nowPlay means that the sound you are playing
                            ProgressList[nowPlay] = mediaPlayer.Position.TotalSeconds * 100 / duration;
                        });
                        Thread.Sleep(10);
                    } while (IsPlaying);
                });

        }
    }

XAML:

    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
        <phone:LongListSelector x:Name="MainLongListSelector" Margin="0,0,-12,0" ItemsSource="{Binding ProgressList}" SelectionChanged="MainLongListSelector_SelectionChanged">
            <phone:LongListSelector.ItemTemplate>
                <DataTemplate>
                  <StackPanel Margin="0,0,0,17">
                        <ProgressBar Height="20" Width="400" Value="{Binding Values}"/>
                  </StackPanel>
                </DataTemplate>
            </phone:LongListSelector.ItemTemplate>
        </phone:LongListSelector>
    </Grid>

视图模型:

public class Progress : INotifyPropertyChanged
    {
        int _values;
        public int Values
        {
            get
            {
                return _values;
            }
            set
            {
                if (value != _values)
                {
                    _values = value;
                    NotifyPropertyChanged("Values");
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(String propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (null != handler)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

 public class MainViewModel : INotifyPropertyChanged
    {
        List<Progress> _progress = new List<Progress>();
        int _values = 100;
        public MainViewModel()
        {
            this.Items = new ObservableCollection<ItemViewModel>();
            _progress.Add(new Progress());
            _progress.Add(new Progress());
            _progress[0].Values = 50;
            _progress[1].Values = 100;

        }
     ...
     }