只需要将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中,也没有办法传递流。
答案 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类。