我正在尝试将MainWindow
中创建的对象传递给我的UserControl
,该对象将会读取并修改它,但它不知道原因。这是我正在使用的代码:
MainWindow
上课:
public partial class MainWindow : Window
{
public SupremeLibrary.Player player = new SupremeLibrary.Player();
public MainWindow()
{
InitializeComponent();
MusicSeekBar = new Components.SeekBar(player);
}
}
SeekBar
用户控件:
public partial class SeekBar : UserControl
{
DispatcherTimer Updater = new DispatcherTimer();
SupremeLibrary.Player player;
/// <summary>
/// Initialize new Seekbar
/// </summary>
public SeekBar()
{
InitializeComponent();
InitializeUpdater();
}
public SeekBar(SupremeLibrary.Player _player)
{
player = _player;
InitializeComponent();
InitializeUpdater();
}
private void InitializeUpdater()
{
Updater.Interval = TimeSpan.FromMilliseconds(100);
Updater.Tick += UpdateSeekBar;
Updater.Start();
}
private void UpdateSeekBar(object sender, EventArgs e)
{
if (player != null)
{
if (player.PlaybackState == SupremeLibrary.PlaybackStates.Playing)
{
if (player.Position.TotalMilliseconds != CustomProgressBar.Value) CustomProgressBar.Value = player.Position.TotalMilliseconds;
if (player.MaxPosition.TotalMilliseconds != CustomProgressBar.Maximum) CustomProgressBar.Maximum = player.MaxPosition.TotalMilliseconds;
}
}
}
private void PB_SeekBar_ChangeValue(object obj, MouseEventArgs e)
{
if (player != null)
{
if (player.PlaybackState == SupremeLibrary.PlaybackStates.Playing)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
player.Position = TimeSpan.FromMilliseconds(e.GetPosition(obj as ProgressBar).X / ((obj as ProgressBar).ActualWidth / 100) * ((obj as ProgressBar).Maximum / 100));
}
}
}
}
另外,如果我使用
,它也可以public SupremeLibrary.Player player = new SupremeLibrary.Player();
as static并在UserControl
中将其称为MainWindow.player
,但它很难看,我不想使用它。
我试图从player
传递MainWindow
作为参考,但它似乎也无效。
答案 0 :(得分:1)
使用MediaElement的示例
用户控制SeekBar
XAML
<UserControl x:Class="CSharpWPF.SeekBar"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DataContext="{Binding RelativeSource={RelativeSource Self}}" >
<Slider Maximum="{Binding TotalMilliseconds}"
Value="{Binding CurrentPosition}"/>
</UserControl>
我在控件中定义了一个Slider,并将最大值和value属性绑定到控件的TotalMilliseconds和CurrentPosition,属性将绑定到控件本身,因为我已将控件的DataContext设置为self
的.cs
public partial class SeekBar : UserControl
{
DispatcherTimer Updater = new DispatcherTimer();
/// <summary>
/// Initialize new Seekbar
/// </summary>
public SeekBar()
{
InitializeComponent();
InitializeUpdater();
}
private void InitializeUpdater()
{
Updater.Interval = TimeSpan.FromMilliseconds(100);
Updater.Tick += UpdateSeekBar;
}
public MediaElement Player
{
get { return (MediaElement)GetValue(PlayerProperty); }
set { SetValue(PlayerProperty, value); }
}
// Using a DependencyProperty as the backing store for Player. This enables animation, styling, binding, etc...
public static readonly DependencyProperty PlayerProperty =
DependencyProperty.Register("Player", typeof(MediaElement), typeof(SeekBar), new PropertyMetadata(null, OnPlayerChanged));
private static void OnPlayerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
SeekBar seekB = d as SeekBar;
if (e.OldValue != null)
{
SeekBar oldSeekB = (e.OldValue as SeekBar);
oldSeekB.Player.MediaOpened -= seekB.Player_MediaOpened;
oldSeekB.Player.MediaEnded -= seekB.Player_MediaEnded;
}
if (seekB.Player != null)
{
seekB.Player.MediaOpened += seekB.Player_MediaOpened;
seekB.Player.MediaEnded += seekB.Player_MediaEnded;
}
}
void Player_MediaEnded(object sender, RoutedEventArgs e)
{
Updater.Stop();
}
private void Player_MediaOpened(object sender, RoutedEventArgs e)
{
if (Player.NaturalDuration.HasTimeSpan)
{
TotalMilliseconds = Player.NaturalDuration.TimeSpan.TotalMilliseconds;
Updater.Start();
}
else
{
CurrentPosition = 0.0;
TotalMilliseconds = 1.0;
}
}
public double CurrentPosition
{
get { return (double)GetValue(CurrentPositionProperty); }
set { SetValue(CurrentPositionProperty, value); }
}
// Using a DependencyProperty as the backing store for CurrentPosition. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CurrentPositionProperty =
DependencyProperty.Register("CurrentPosition", typeof(double), typeof(SeekBar), new PropertyMetadata(1.0, OnCurrentPositionChange));
private static void OnCurrentPositionChange(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
SeekBar seekB = d as SeekBar;
if (seekB.Player != null)
{
seekB.Player.Position = TimeSpan.FromMilliseconds(seekB.CurrentPosition);
}
}
public double TotalMilliseconds
{
get { return (double)GetValue(TotalMillisecondsProperty); }
set { SetValue(TotalMillisecondsProperty, value); }
}
// Using a DependencyProperty as the backing store for TotalMilliseconds. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TotalMillisecondsProperty =
DependencyProperty.Register("TotalMilliseconds", typeof(double), typeof(SeekBar), new PropertyMetadata(0.0));
private void UpdateSeekBar(object sender, EventArgs e)
{
if (Player != null && TotalMilliseconds > 1)
{
CurrentPosition = Player.Position.TotalMilliseconds;
}
}
}
我做了什么
在主窗口中使用
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<MediaElement x:Name="media"
Source="Wildlife.wmv" />
<l:SeekBar Grid.Row="1"
Player="{Binding ElementName=media}" />
</Grid>
我只是将媒体元素绑定到我的SeekBar控件的Player属性
通过这种方式,我没有在代码背后做任何硬编码,也可以通过接口,你可以在你的搜索栏和播放器之间实现更大的解耦
这只是一个简单的例子,你可以在上面的例子中使用你的自定义播放器和进度控制来实现你的结果。