WPF的MVVM模式:模型与ViewModel

时间:2018-07-16 13:01:16

标签: c# mvvm

我无法真正解决以下问题:

我在应用程序中拥有的只是用于用户输入的$apiUrl = "https://www.zohoapis.com/crm/v2/Leads/" . {valid record id here}; $fields = json_encode(array("data" => array(["City" => "Egham"]))); // *strlen must be called after defining the variable. So moved headers down to $fields* $headers = array( 'Content-Type: application/json', 'Content-Length: ' . strlen($fields), sprintf('Authorization: Zoho-oauthtoken %s', {valid auth token here}) ); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $apiUrl); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT"); curl_setopt($ch, CURLOPT_POSTFIELDS, $fields); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60); curl_setopt($ch, CURLOPT_TIMEOUT, 60); $result = curl_exec($ch); curl_close($ch); ,用于对该输入执行背景计算的textboxbutton。想象一下我必须使用MVVM,所以我有textblockviewviewmodel类。

我将视图中的控件(modeltextboxbutton)绑定到相应属性和命令上的textblock。但是,我不确定viewmodel功能应该在哪里结束。例如,下面是构建应用程序的一种方法吗?

型号:

viewmodel

ViewModel:

public class Model
{

    public string Input { get; set; }
    public string Output { get; set; }

    public void FancyMethod ()
    {
       // Use input to calculate output
    }

}

3 个答案:

答案 0 :(得分:2)

如果要保持干净的图层模型,则public Model model {get; set;}中不应包含ViewModel

例如,如果您有一个针对某些业务模型的命令,则您的结构应如下所示:

//you don't have this one... but well, maybe other cases have
public class SomeService : ISomeService
{
    //member of ISomeService
    public void SomeFancyMethod(Model model)
    {
        //do stuff..
    }
}

public class Model //might be database, or domain model.
{
   public string Input { get; set; }
   public string Output { get; set; }
}

对于您的视图模型,它将变成这样:

public class ViewModel
{
    private ISomeService _someService;

    //note: someService is passed through a IoC service like ninject, unity, autofac etc.
    public ViewModel(ISomeService someService)
    {
        _someService = someService;
        //initialize the command:
        command = new RelayCommand(() =>
        {    
            _someService .SomeFancyMethod(new Model()
            {
                //properties could be mapped with an automapper.
            });
        });
    }

    public ICommand command {get; private set;}
    public string Input {get; set;}
    public string Output {get; set;}
 }

注意:还涉及其他一些技术:


“那么,为什么要使其变得'复杂'?您只是在制作副本。” ,一种常见的反对这种模式的论点:

嗯:

  1. 这并不复杂
  2. 执行此操作将分隔您的图层。这意味着您的数据层中的更改不会破坏您的视图。从长远来看,您会从中受益,因为变革将来临,您需要维护代码。

答案 1 :(得分:1)

我想user_id包含您的业务逻辑,并产生了您想要在视图中显示的值。在这种情况下,FancyMethod()属于您的模型,因为它包含一些相同的业务逻辑,而不管它是在客户端应用程序还是其他组件的上下文中执行。

因此您的模型看起来应该像这样,即它接受输入并产生输出,但是它不公开视图可能绑定到的任何属性:

FancyMethod()

然后,您可以在模型中注入视图模型,并在用户执行视图时通过单击视图中的public class Model { public string FancyMethod(string input) { // Use input to calculate output } } 来调用FancyMethod

Button

显然,视图模型类还应该实现public class ViewModel { private readonly Model _model; public ViewModel(Model model) { _model = model; command = new RelayCommand(Execute, CanExecute); } public string Input { get; set; } public string Output { get; set; } public ICommand command { get; private set; } private bool CanExecute(object _) { return !string.IsNullOrEmpty(Input); } private void Execute(object _) { Output = _model.FancyMethod(Input); } } 接口,并向视图发出更改通知。

简而言之,业务逻辑属于模型,而应用程序逻辑属于视图模型。例如,用户单击INotifyPropertyChanged时所发生的事情。

答案 2 :(得分:0)

我认为没有必要超越另一个类中的InputOutput属性。其原因是属性反映了视图的输入和输出。因此,它们必须位于视图模型中。 您可以在服务类中胜过SomeFancyMethod,以将逻辑从与mvc类似的视图模型中分离出来。