简体   繁体   中英

How can I access and fire Events from a MediaElement from a View in a ViewModel?

I'm creating a Windows 10 app and I am implementing speech functionality. The user needs to be able to listen to the whole speech, respond with voice, and then receive a response back. But, I'm having troubles making this purely MVVM.

Okay, for MediaElement.Ended, I can just use a behavior, right? Set the Ended behavior to my own command which fires the method I want?

As for setting the source to synthesized text and setting AutoPlay to true, I can just bind those to properties in my ViewModel.

But, MediaElement.Play()...How do I fire this method from a ViewModel if I can't access the MediaElement?

I understand I can do some "hacks" to make it work or use the code-behind, but my aim is to do this "purely MVVM", where my ViewModel knows nothing of the view and any view elements.

Thanks anyone for the help.

You could do something like this:

MVVM Project:

-ServiceLocator.cs

public class ServiceLocator
{
    public static ServiceLocator Instance = new ServiceLocator();

    private ServiceLocator()
    {
    }

    private readonly IDictionary<Type, Type> TypeMap = new Dictionary<Type, Type>();

    private readonly IDictionary<Type, object> TypeMapInstances = new Dictionary<Type, object>();

    public void Register<TInterface, TClass>()
    {
        TypeMap.Add(typeof(TInterface), typeof(TClass));
    }

    public void Register<TClass>(object instance)
    {
        TypeMapInstances.Add(typeof(TClass), instance);
    }

    public T GetService<T>()
    {
        Type type = typeof(T);
        object resolvedType = null;

        try
        {
            if (TypeMapInstances.ContainsKey(type))
            {
                resolvedType = TypeMapInstances[type];
            }
            else
            {
                resolvedType = Activator.CreateInstance(TypeMap[type]);
                TypeMapInstances.Add(type, resolvedType);
            }
        }
        catch (Exception)
        {
            return default(T);
            //throw new Exception(string.Format("Could not resolve type {0}", type.FullName));
        }

        return (T)resolvedType;
    }
}

-IMediaElementService.cs

public interface IMediaElementService
{
    void Play();
}

-YourVMClass.cs

public void Foo()
{
    var mediaElementService = ServiceLocator.Instance.GetService<IMediaElementService>();
    mediaElementService.Play();
}

Client Project:

-MediaElementService.cs

public class MediaElementService : IMediaElementService
{
    public void Play()
    {
        App.MediaElement.Play();
    }
}

-App.cs

public static MediaElement MediaElement;

private void OnLaunched(LaunchActivatedEventArgs e)
{
    ServiceLocator.Instance.Register<IMediaElementService, MediaElementService>();
}

-YourView.xaml

<MediaElement x:Name="_mediaElement" />

-YourView.xaml.cs

public YourView(){
    InitializeComponent();
    App.MediaElement = _mediaElement;
}

And that's all, although this is only one of several ways that could achieve the same.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM