将对象传递给将控制它的UserControl

时间:2014-06-08 12:41:54

标签: c# wpf user-controls

我正在尝试将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作为参考,但它似乎也无效。

1 个答案:

答案 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;
        }
    }
}

我做了什么

  • 定义属性要在UI处绑定的媒体元素的播放器
  • 附加了MediaOpened和MediaEnded,用于启动和停止计时器,以及更新持续时间。
  • 在控制UI中为我的滑块控件定义了当前位置和总持续时间的属性
  • 并且在更改CurrentPosition时,我会更新玩家的位置。

在主窗口中使用

<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属性

通过这种方式,我没有在代码背后做任何硬编码,也可以通过接口,你可以在你的搜索栏和播放器之间实现更大的解耦

这只是一个简单的例子,你可以在上面的例子中使用你的自定义播放器和进度控制来实现你的结果。