- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在 Windows Phone 8 上编写一个音频应用程序。我创建了一个 MediaElement 和一个搜索栏( slider ):
<MediaElement x:Name="player" CurrentStateChanged="GetTrackDuration" />
<Slider x:Name="playerSeekBar" Value="{Binding ElementName=player, Path=Position,
Mode=TwoWay, Converter={StaticResource PositionConverter}}" SmallChange="1" LargeChange="1"/>
这是我的转换器代码:
public class PositionConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
double position = 0;
TimeSpan timespan = TimeSpan.Parse(value.ToString());
position = timespan.TotalSeconds;
return position;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return TimeSpan.FromSeconds((double)value);
}
}
这是 CurrentStateChanged 事件代码:
private void GetTrackDuration(object sender, RoutedEventArgs e)
{
var player = (MediaElement)sender;
if (player.CurrentState == System.Windows.Media.MediaElementState.Playing)
playerSeekBar.Maximum = player.NaturalDuration.TimeSpan.TotalSeconds;
}
一切似乎都正常,但是绑定(bind)到 slider 有一个问题 - 它不会更新,直到我点击应用程序内部的某个地方 - 我的意思是我可能会点击一个未与 slider 连接的按钮或媒体元素或空白空间。单击 slider 后, slider 正在更新,一切正常。顺便说一句,音乐播放正常 - 即使在 slider 未更新的开始时也是如此。我试图在互联网上查看,但是我不确定要问什么,这就是为什么我向您寻求帮助。如果有人知道我可以在哪里搜索解决方案,我将不胜感激!:)
提前感谢您的帮助!
最佳答案
当 Slider 获得 Focus 时看起来像个问题,我试图找到重定向 Focus 的解决方案,但到目前为止 - 我还没有找到它。相反,我有一个不同的建议和对您的代码的一些评论:
在媒体打开时而不是在 PlayState 更改时获取轨道持续时间:
private void player_MediaOpened(object sender, RoutedEventArgs e)
{
playerSeekBar.Maximum = (sender as MediaElement).NaturalDuration.TimeSpan.TotalSeconds;
}
您的 Slider 可能会随着 MediaElement 位置的每次微小变化而更新。我认为这不是必需的 - 它可以每秒更新一次。所以我的建议是 - 将您的 Slider 绑定(bind)到一个属性,并每秒通知一次 PropertyChanged(使用 DispatcherTimer
):
// In this case we need INotifyPropertyChanged -
public partial class MainPage : PhoneApplicationPage, INotifyPropertyChanged
{
// implementing interface
public event PropertyChangedEventHandler PropertyChanged;
public void RaiseProperty(string property = null)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(property));
}
// Property for Binding
public double SlideValue
{
get { return player.Position.TotalSeconds; }
set { player.Position = TimeSpan.FromSeconds(value); }
}
DispatcherTimer timer = new DispatcherTimer(); // timer
// Get the duration when Media File is opened
private void player_MediaOpened(object sender, RoutedEventArgs e)
{
playerSeekBar.Maximum = (sender as MediaElement).NaturalDuration.TimeSpan.TotalSeconds;
}
public MainPage()
{
InitializeComponent();
this.DataContext = this; // Set the DataContext
Play.Click += Play_Click; // My play method
timer.Interval = TimeSpan.FromSeconds(1);
timer.Tick += (s, e) => { RaiseProperty("SlideValue"); };
}
private void Play_Click(object sender, RoutedEventArgs e)
{
player.AutoPlay = true;
player.Source = new Uri("music.mp3", UriKind.RelativeOrAbsolute);
timer.Start(); // DON'T forget to start the timer.
}
在这种情况下,您不再需要转换器,您的 XAML 代码可能如下所示:
<MediaElement x:Name="player" MediaOpened="player_MediaOpened"/>
<Slider x:Name="playerSeekBar" Value="{Binding SlideValue, Mode=TwoWay}" SmallChange="1" LargeChange="1"/>
上面的代码可能还需要一些改进,但工作得很好。
编辑 - 没有 DataBinding 和 INotifyPropertyChanged 的方法
您还可以在不使用绑定(bind)的情况下以更简单的方式完成您的任务,只需使用 Timer
和 LostMouseCapture
:
public partial class MainPage : PhoneApplicationPage
{
private double totalSeconds = 1;
DispatcherTimer timer = new DispatcherTimer();
private void player_MediaOpened(object sender, RoutedEventArgs e)
{
totalSeconds = (sender as MediaElement).NaturalDuration.TimeSpan.TotalSeconds;
}
public MainPage()
{
InitializeComponent();
Play.Click += Play_Click;
timer.Interval = TimeSpan.FromSeconds(1);
timer.Tick += (s, e) => { playerSeekBar.Value += (double)(1 / totalSeconds); };
playerSeekBar.LostMouseCapture += (s, e) =>
{ player.Position = TimeSpan.FromSeconds(playerSeekBar.Value * totalSeconds); };
}
private void Play_Click(object sender, RoutedEventArgs e)
{
player.AutoPlay = true;
player.Source = new Uri("music.mp3", UriKind.RelativeOrAbsolute);
timer.Start(); // DON'T forget to start the timer.
}
}
在 XAML 中:
<MediaElement x:Name="player" MediaOpened="player_MediaOpened"/>
<Slider x:Name="playerSeekBar" Value="0" SmallChange="0.01" Maximum="1.0"/>
希望这对您有所帮助。
关于c# - Windows Phone 8 slider 绑定(bind)仅在单击后起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22115537/
我是一名优秀的程序员,十分优秀!