繁体   English   中英

使用 MVVM,如何在低级服务和视图模型之间建立通信线路?

[英]Using MVVM, how can I establish a line of communication between a low level service and view model?

我正在使用 Prism 和 Unity 实现具有蓝牙连接的媒体播放器应用程序。

我正在使用的应用程序流程如下:

  1. 用户在远程设备(手机/平板电脑)上发出命令
  2. 桌面应用程序通过蓝牙服务接收Play命令
  3. 更高级别的服务处理元数据并告诉VideoPlaybackViewModel开始播放

到目前为止我所拥有的

蓝牙服务还没有实现,因为我想先完成其他元素。 当需要这样做时,我将遵循这个示例( https://github.com/saramgsilva/BluetoothSampleUsing32feet.Net )。

按照这个问题( MVVM 模式违规: MediaElement.Play() ),我已经实现了VideoPlaybackViewVideoPlaybackViewModel

VideoPlaybackView

    <UserControl x:Class="Views.VideoPlaybackView"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:ia="http://schemas.microsoft.com/expression/2010/interactivity"
                 xmlns:prism="http://prismlibrary.com/"
                 prism:ViewModelLocator.AutoWireViewModel="True"
                 x:Name="MediaService">
        <ia:Interaction.Triggers>
            <ia:EventTrigger EventName="Loaded">
                <ia:InvokeCommandAction Command="{Binding LoadedCommand}" CommandParameter="{Binding ElementName=MediaService}" />
            </ia:EventTrigger>
        </ia:Interaction.Triggers>
        <Grid>
            <MediaElement 
                x:Name="VideoPlayer"
                Source="{Binding VideoSource}" />
        </Grid>
    </UserControl>

VideoPlaybackViewModel

    public class VideoPlaybackViewModel : BindableBase {
        private Uri _videoSource;

        public IMediaService MediaService { get; private set; }

        public Uri VideoSource {
            get => _videoSource;
            set => SetProperty(ref _videoSource, value);
        }

        private DelegateCommand<IMediaService> _loadedCommand;

        public DelegateCommand<IMediaService> LoadedCommand {
            get {
                if (_loadedCommand == null) {
                    _loadedCommand =
                        new DelegateCommand<IMediaService>((mediaService) => { MediaService = mediaService; });
                }
                return _loadedCommand;
            }
        }
    }

这些在加载VideoPlaybackModule时初始化:

    public class VideoPlaybackModule : IModule {
        private IUnityContainer _container;
        private IRegionManager _regionManager;

        public VideoPlaybackModule(IUnityContainer container, IRegionManager regionManager) {
            _container = container;
            _regionManager = regionManager;
        }

        public void Initialize() {
            _regionManager.RegisterViewWithRegion("MainRegion", typeof(VideoPlaybackView));
        }
    }

我使用模块是因为我想学习它们。

目标

我想要的是某种控制器,可以从蓝牙服务接收事件,解析元数据,更新MediaElement.Source ,并以某种方式向VideoPlayerViewModel发送命令以实际播放视频。

尝试

我已经看到了实现控制器的想法,但我不确定我应该如何初始化它。 我提出以下问题: - 如何连接控制器以响应来自蓝牙服务的蓝牙命令? - 控制器是否应该保留对VideoPlaybackViewModel的引用以执行命令?

我认为服务也适用于此。 例如,如果我创建了一个VideoPlaybackService ,将如何使用该服务? 类似于控制器的想法,它需要在将命令发送到VideoPlayerViewModel之前处理元数据的处理。

如何使用 Prism 和 Unity 来实现这种模式?

有很多方法可以做到这一点,但似乎Mediator Pattern可能是您正在寻找的机器人。 这将有助于减少您担心的耦合

中介模式

使用中介者模式,对象之间的通信被封装在中介者对象中。 对象不再直接相互通信,而是通过中介进行通信。 这减少了通信对象之间的依赖关系,从而减少了耦合。

耦合

在软件工程中,耦合是软件模块之间的相互依赖程度; 衡量两个例程或模块的紧密程度; 模块之间关系的强度。

MVVM Light 之类的东西中,您可以使用MVVM Light Messenger

它有点像Pub/Sub事件,当您注册/订阅消息时,您的Decoupled类可以发布/发送所述消息。

但是,由于您提到您使用的是Prism ,因此您可以使用EventAggregator 这又是一个 Pub/Sub 安排。

在此处输入图片说明

从您的服务发送事件的示例

this.eventAggregator  
    .GetEvent<PubSubEvent<BlueToothData>>()  
    .Publish(new BlueToothData { SomeData = someData });

ViewModel 中的接收和事件示例

var subscriptionToken = this.eventAggregator                             
                            .GetEvent<PubSubEvent<BlueToothData>>()                          
                            .Subscribe((details) =>  
                                   {       
                                       // what ever you want to do here;        
                                   });  

注意:我不使用 Prism,但是 EventAggregator 有很多可用的资源

其他资源

带有 MVVM 的 WPF 中的 Prism 事件聚合器

使用事件聚合器模式进行通信

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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