如何将流从ViewModel发送到XAML页面上的MediaElement?

时间:2016-06-17 17:15:03

标签: mvvm-light

只需要将ViewModel(继承自MVVM Light ViewModelBase)的文本字符串说成XAML页面上的MediaElement

var synthesisStream = await synthesizer.SynthesizeSsmlToStreamAsync(text);
media.AutoPlay = true;
media.SetSource(synthesisStream, synthesisStream.ContentType);
media.Play();

上面的代码没有ViewModel的分离。我们看到media直接在代码隐藏中处理。

在我的ViewModel中,我停在了

var synthesisStream = await synthesizer.SynthesizeSsmlToStreamAsync(text);

var msg=new PlaySpeechSynthesisStreamMessage(synthesisStream);
Messenger.Default.Send<PlaySpeechSynthesisStreamMessage>(msg);

对于消息:

public class PlaySpeechSynthesisStreamMessage
{
    public SpeechSynthesisStream Stream { get; set; }

    public PlaySpeechSynthesisStreamMessage(SpeechSynthesisStream stream)
    {
        Stream = stream;
    }
}

Messenger是处理这种情况的正确方法吗?我们如何编写RelayCommand或其他内容来将流传递给media

相关文章MVVM pattern violation: MediaElement.Play()似乎解决了这个问题,但它不在MVVM Light中,也没有办法传递流。

1 个答案:

答案 0 :(得分:0)

我认为一条消息是处理这种情况的好方法。 您只需要补充ViewModel中的消息发送,并在View:

中处理它
Messenger.Default.Register<PlaySpeechSynthesisStreamMessage>(this, msg => {
    media.AutoPlay = true;
    media.SetSource(msg.Stream, msg.Stream.ContentType);
    media.Play();
});

或者,您可以使用您引用的问题中描述的事件方法。在这种情况下,您必须定义一个继承自EventArgs且具有类型SpeechSynthesisStream属性的类,然后按如下方式定义您的事件:

public event EventHandler<YourEventArgsClass> PlaySpeechSynthesisStreamEvent;

并以这种方式提高:

var synthesisStream = await synthesizer.SynthesizeSsmlToStreamAsync(text);
var eventArgs = new YourEventArgsClass(synthesisStream);
if (PlaySpeechSynthesisStreamEvent != null)
    PlaySpeechSynthesisStreamEvent(this, eventArgs);

在这种情况下,您当然必须在视图中处理事件。

我发现事件处理程序的解决方案比带消息的解决方案有点棘手,因为您必须将事件处理连接到View的DataContext,并且根据应用程序的结构,DataContext属性为从View生命周期的开始,View无法始终可用:例如,在很多情况下,我倾向于在导航到视图期间通过导航服务和/或Bootstrapper设置它:在这种情况下,DataContext在View的costructor,因此无法在那里连接事件处理程序。因此,您必须找到另一个地方来连接它,记住在视图的生命周期中可以多次调用诸如OnNavigatedFrom(例如,在Windows 10 UWP应用程序中)的方法,并且我们当然不希望连接事件处理程序不止一次。 如果框架公开它(例如在Windows 10 UWP中),则DataContextChanged事件可以是连接与ViewModel相关的事件处理程序的好地方(如果View的实例可以与不同的实例一起使用,则可能删除以前的事件处理程序)应用程序生命周期内的ViewModel类。