2016-06-17 4 views
0

Просто нужно говорить текстовую строку из ViewModel (унаследованной от MVVM Light ViewModelBase) до MediaElement на странице XAML.Как отправить поток из ViewModel в MediaElement на странице XAML?

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

Я думаю, что сообщение является хорошим решением для решения такой ситуации. Вы просто должны дополнять отправку сообщения в ViewModel с обработкой его в представлении:

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); 

В этом Конечно, вам придется обрабатывать событие в представлении.

Я нашел решение с обработчиком событий немного сложнее, чем сообщение с сообщениями, потому что вам придется связать обработку событий с DataContext представления и, в зависимости от структуры приложения, свойство DataContext View не всегда может быть доступен с самого начала жизни View View: например, во многих случаях я стараюсь установить его через службу навигации и/или Bootstrapper во время навигации к представлению: в этом случае DataContext имеет значение null в конструктор представления, поэтому невозможно обработать обработчик событий. Таким образом, вам нужно найти другое место, чтобы подключить его, помня, что такие методы, такие как OnNavigatedFrom (например, в приложениях с Windows 10 UWP), можно назвать более одного раза в жизненном цикле представления и, конечно же, мы не хотим связывать событие обработчик не один раз. Если структура предоставляет его (например, в Windows 10 UWP), событие DataContextChanged может быть хорошим местом для проводки обработчиков событий, связанных с ViewModel (и, возможно, для удаления предыдущих, если экземпляр представления может использоваться с другим экземпляром класса ViewModel в течение всего срока службы приложения).