我的视图内部有一个控件,它能够生成一个保存在我可以指定的路径上的图像(以及其他一些数据)。我不拥有此控件,无法获取生成图像更改的界面。我不太确定如何使用MVVM来处理这个问题。
快速而肮脏的方式是我的视图定义一个获取所需路径的方法,并让viewmodel调用该方法。
View:
public void GenerateImage(string path) {
_control.SaveImage(path);
}
ViewModel:
(actually this is the body of a Command) {
var path = GeneratePath();
_view.GenerateImage(path);
...
}
我不喜欢这样,因为我觉得viewmodels并不是要直接引用视图,而是代表视图的状态并通过属性绑定进行通信。它有效,而我正在等待答案时这样做。我想找到解决办法。
我可以变得可爱并让视图通过Execute()参数将控件的引用传递给Command(我在Xamarin Forms中),并使用命令强制转换并进行调用。这看起来像猪上的口红,因为它使视图模型仍然知道视图中的特定类。但在写这一段时,我想我想出了一个我喜欢的解决方案。
I / could / create:
interface IGenerateImage {
void GenerateImage(string path);
}
明显的实现会将调用委托给封装控件。我觉得如果视图通过了IGenerateImage
,那么我就不会创建我想要避免的viewmodel-to-view依赖项,而且我可以测试逻辑而无需实例化昂贵的UI类。
我喜欢这个答案,但我很确定我有一个明显的解决方案。是否有其他有用的处理方式?或者,如果viewmodel引用视图,这不是什么大不了的事吗?
答案 0 :(得分:3)
您永远不希望视图模型了解有关视图的任何信息。
有点不清楚你能做什么,不能改变你的帖子,所以我假设你可以改变V / VM,但不是_control。
最简单的方法是在View模型中创建一个View可以订阅的事件。
这样的事情:
查看:
// Constructor
public View()
{
// However you're setting your VM, i.e. DI or new-ing up the VM
// Subscribe to the event
vm.ImageGeneratedEvent += this.OnImageGeneratedEvent;
}
private void OnImageGeneratedEvent(object sender, ImageGeneratedEventArgs args)
{
// Call your SaveImage in the event handler
_control.SaveImage(args.Path);
}
查看型号:
public event EventHandler<ImageGeneratedEventArgs> ImageGeneratedEvent;
// Command body
{
var path = GeneratePath();
// Send event to the View
this.NotifyImageGeneratedEvent(path)
}
private void NotifyImageGeneratedEvent(string path)
{
ImageGeneratedEventArgs args = new ImageGeneratedEventArgs(path);
if (this.ImageGeneratedEvent!= null)
{
this.ImageGeneratedEvent(this, args);
}
}
ImageGeneratedEventArgs:
public class ImageGeneratedEventArgs : EventArgs
{
public string Path { get; set; }
public ImageGeneratedEventArgs(string path)
{
this.Path = path;
}
}