ViewModel应该直接引用View对象吗?

时间:2014-08-21 21:29:05

标签: c# mvvm xamarin.forms

我的视图内部有一个控件,它能够生成一个保存在我可以指定的路径上的图像(以及其他一些数据)。我不拥有此控件,无法获取生成图像更改的界面。我不太确定如何使用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引用视图,这不是什么大不了的事吗?

1 个答案:

答案 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;
    }
}