[英]WPF MVVM: INPC and mediating communication between view model & model
[英]Using MVVM, how can I establish a line of communication between a low level service and view model?
我正在使用 Prism 和 Unity 实现具有蓝牙连接的媒体播放器应用程序。
我正在使用的应用程序流程如下:
Play
命令VideoPlaybackViewModel
开始播放蓝牙服务还没有实现,因为我想先完成其他元素。 当需要这样做时,我将遵循这个示例( https://github.com/saramgsilva/BluetoothSampleUsing32feet.Net )。
按照这个问题( MVVM 模式违规: MediaElement.Play() ),我已经实现了VideoPlaybackView
和VideoPlaybackViewModel
。
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 有很多可用的资源
其他资源
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.