MediaElement.play() from within ViewModel

房东的猫 提交于 2019-12-04 13:26:48

问题


I'm struggling with the following issue:

I am building a WP8 application using the MVVM patern. I have a media element on my view.xaml and the logic to control this media element (for example, play, stop, pause and volume) in my viewmodel.cs.

How do I play a sound on this media element from my viewmodel using binding. Without destroying the purpose and structure of MvvM.

(PS: i've seen the following post, but i'm not sure in how to implement it? Link to post)


回答1:


You can bind Media Element directly from the view model

in xaml:

<ContentControl Content="{Binding MediaElementObject}"/>

in ViewModel:

private MediaElement _mediaElementObject;

public MediaElement MediaElementObject
{
   get { return _mediaElementObject; }
   set { _mediaElementObject = value;RaisePropertyChanged(); }
}

And on OnNavigatedTo Override method you can create it's new object & can register it's events.

MediaElementObject=new MediaElement();

So that you can do all thing from the viewmodel itself.




回答2:


The answers above make use of MediaElement in the ViewModel. This element is a View-side component the VM should remain agnostic of.

One way to implement this would be exposing an event in your ViewModel via an interface that exposes that event, then have the view respond to that event by running its MediaElement, via code-behind, or perhaps using interactivity triggers.

ViewModel:

public interface ISoundPlayer
{
  event Action Play();
}    

public class MyViewModel : ViewModelBase, ISoundPlayer
{
  public event Action Play;
}

View:

public class MyView : UserControl
{
  ISoundPlayer _SoundPlayer;

  public MyView()
  {
    DataContextChanged += OnDataContextChanged;
    Unloaded += OnUnloaded;
  }  

  void OnDataContextChanged(DependencyObject sender, DataContextChangedEventArgs args)
  {
    if (DataContext is ISoundPlayer player && _SoundPlayer != player)
    {
      if (_SoundPlayer != null)
        _SoundPlayer.Play -= OnPlay;

      _SoundPlayer = player;
      _SoundPlayer.Play += OnPlay;
    }    
  }

  void OnUnloaded(object sender, RoutedEventArgs e)
  {
    if (_SoundPlayer != null)
      _Metronome.Play -= OnPlay;
  }

  void OnPlay() => myMediaElement.Play();
}



回答3:


The answer of asitis is great.And I show you my detail code:(use caliburn.micro so don't need to bind name)

View

    <Grid>
         <ContentControl Content="{Binding MediaElementObject}"/>
    </Grid>

    <StackPanel Orientation="Horizontal">
         <Button x:Name="ButtonPlay" Content="Play" Width="220px" Margin="20,5"/>
         <Button x:Name="ButtonStop" Content="Stop" Width="220px" Margin="20,5"/>
         <Button x:Name="ButtonForward" Content="Forward(30s)" Width="220px" Margin="20,5"/>
         <Button x:Name="ButtonBack" Content="Back(30s)"Width="220px" Margin="20,5"/>
     </StackPanel>

ViewModel

    private MediaElement _mediaElementObject = new MediaElement();
    public MediaElement MediaElementObject
    {
        get { return _mediaElementObject; }
        set
        {
            _mediaElementObject = value;
            NotifyOfPropertyChange(() => MediaElementObject);
        }
    }

    public void ButtonPlay()
    {
        MediaElementObject.Source =new Uri( @"C:\Users\admin\Videos\XXXXXX.wmv");
        MediaElementObject.LoadedBehavior = MediaState.Manual;
        MediaElementObject.UnloadedBehavior = MediaState.Manual;
        MediaElementObject.Play();
    }     

    public void ButtonStop()
    {
        MediaElementObject.Stop();
    }
    public void ButtonForward()
    {
        MediaElementObject.Position = _mediaElementObject.Position + TimeSpan.FromSeconds(30);
    }
    public void ButtonBack()
    {
        MediaElementObject.Position = _mediaElementObject.Position - TimeSpan.FromSeconds(30);
    }

May can help someone:)



来源:https://stackoverflow.com/questions/22606067/mediaelement-play-from-within-viewmodel

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!