c# - instancelocator - xamarin stacklayout content binding
En MVVM, ¿cada ViewModel está acoplado a un solo modelo? (7)
En una implementación de MVVM, ¿cada ViewModel
acoplado a un solo Model
?
Estoy tratando de implementar el patrón MVVM en un proyecto, pero descubrí que a veces, una View
puede necesitar información de varios Models
.
Por ejemplo, para UserProfileView
, su UserProfileViewModel
puede necesitar información de UserAccountModel
, UserProfileSettingsModel
, UserPostsDataModel
, etc.
Sin embargo, en la mayoría de los artículos que leí sobre MVVM, ViewModel solo consiste en un Modelo a través de Dependency Injection. Entonces el constructor toma solo un Modelo.
¿Cómo funcionaría ViewModel
cuando tenga que obtener información de múltiples Models
? ¿O tal situación ocurriría alguna vez en MVVM?
PD: No estoy usando el Prism o el Unity Framework. Estoy tratando de implementar patrones similares en un proyecto en el que estoy trabajando y que no usa Prism o Unity. Es por eso que necesito entender exactamente cómo funcionan algunas de estas cosas.
En mi comprensión del patrón MVVM, el único requisito práctico es que View obtenga todos sus datos de las propiedades de un ViewModel (probablemente a través de un mecanismo de enlace). ViewModel es una clase que elabora específicamente para esa vista y asume la responsabilidad de rellenarse según sea necesario. Podría pensar que es como ActiveRecord para la vista.
Como tal, no importa lo que haga dentro de ViewModel para obtener los datos que deberían mostrar sus propiedades. Puede obtenerlo consultando algunos servicios, leyendo uno o más modelos de entidades comerciales, generando en el acto, o todo lo anterior. Es perfectamente normal que necesite una combinación de todas estas cosas para tener una vista funcional.
Como en cualquier patrón de presentación, el objetivo es simplemente separar el proceso de mostrar algunos datos en la pantalla, a partir del proceso de obtención de esos datos. De esta forma puede probar cada parte del proceso por separado.
Editar: Aquí hay un pequeño pero afortunado ejemplo completo del flujo de dependencias.
// Model/service layer
public class MyModelA
{
public string GetSomeData()
{
return "Some Data";
}
}
public class MyModelB
{
public string GetOtherData()
{
return "Other Data";
}
}
// Presentation layer
public class MyViewModel
{
readonly MyModelA modelA;
readonly MyModelB modelB;
public MyViewModel(MyModelA modelA, MyModelB modelB)
{
this.modelA = modelA;
this.modelB = modelB;
}
public string TextBox1Value { get; set; }
public string TextBox2Value { get; set; }
public void Load()
{
// These need not necessarily be populated this way.
// You could load an entity and have your properties read data directly from it.
this.TextBox1Value = modelA.GetSomeData();
this.TextBox2Value = modelB.GetOtherData();
// raise INotifyPropertyChanged events here
}
}
public class MyView
{
readonly MyViewModel vm;
public MyView(MyViewModel vm)
{
this.vm = vm;
// bind to vm here
}
}
// Application layer
public class Program
{
public void Run()
{
var mA = new MyModelA();
var mB = new MyModelB();
var vm = new MyViewModel(mA, mB);
var view = new MyView(vm);
vm.Load();
// show view here
}
}
Me aseguraré de que comprenda la diferencia entre view, viewmodel y todas las demás clases de modelos. ViewModel es el objeto modelo que está lleno de datos a los que se puede vincular la vista. Solo existe para proporcionar datos a la vista, lo que hace que el objeto ViewModel sea comprobable por unidad, y toda la lógica de negocios separada de la vista. Por lo tanto, puede desarrollar su lógica de negocios por completo sin usar la vista en sí misma, y puede reemplazar la vista simplemente con la construcción o el uso de otra vista y el enlace a las propiedades del objeto ViewModel. Si una vista está llena de campos de texto vacíos, por ejemplo, los contenidos de los campos de texto se pueden vincular a diferentes propiedades del modelo de vista.
Por lo general, solo debería haber un modelo de vista. PERO si es demasiado complejo, puede usar subpropiedades de los objetos enlazados como se describe en Enlace a ViewModel.SubClass.Property (sub-propiedad)
El ViewModel puede obtener los datos que devuelve a la vista de muchas fuentes diferentes, objetos comerciales, bases de datos, lo que sea.
Puede usar múltiples modelos en un modelo de vista. El objetivo del modelo de vista es abstraer la capa de negocio / datos (es decir, el modelo).
Sin embargo, usar más de un modelo generalmente indica que la vista es demasiado grande. Es posible que desee dividirlo en controles de usuario (que tienen sus propios modelos de vista).
Un ViewModel puede y en muchos casos usa múltiples Modelos. Es en sí mismo un "Modelo" de su vista.
Considere una pantalla de perfil en la que un usuario ingrese su información personal, incluida la dirección. Si la dirección se almacena en una tabla de "direcciones" y el resto en una tabla de "perfil", ViewModel utiliza los modelos de perfil y de dirección para crear un modelo de vista unificado.
Como mencionó en su respuesta, muchas veces puede usar controles de usuario para lograr una relación de uno a uno, pero también puede introducir una complejidad innecesaria al intentar esto el 100% del tiempo.
Usualmente hay un ViewModel por modelo. Estos ViewModels contienen la lógica para manejar los datos del modelo. Por otro lado, cada vista tiene su propio modelo de vista, también. Entonces esto significa:
class ModelA
{
bool TestValue{get;set;}
}
class ViewModelA<ModelA>
{
ValueViewModel<bool> TestValue{get; private set;}
public ViewModelA(ModelA model)
{
base.Model = model;
this.Initialize();
}
}
class ModelB
{
string Username;
}
class ViewModelB<ModelB>
{
ValueViewModel<string> Username{get; private set;}
public ViewModelB(ModelB model)
{
base.Model = model;
this.Initialize();
}
}
Estos son los ViewModels que encapsulan los modelos. Las vistas tienen sus propios ViewModels:
public ViewModelForExactlyOneView
{
public ViewModelA{get;set;}
public ViewModelB{get;set;}
}
Para responder a su pregunta, ViewModel1 hace referencia a ViewModelA y ViewModelB. La Vista, por lo tanto, puede obtener sus datos de ViewModel1.ViewModelA.TestValue
.
solo use el modelo de Usuario en su vista
public partial class User : Login
{
public string Password { get; set; }
public List<Customer> customer { get; set; }
}
en este, el inicio de sesión de otro modelo se hereda y el modelo de cliente también se utiliza en este modelo.
un modelo de vista contiene la "lógica de vista", por lo que todo lo que desea mostrar en la vista queda expuesto a través del modelo de vista. si desea mostrar datos de diferentes "modelos", su viewmodel agregará esto y la vista se podrá enlazar.
el propósito principal de mvvm fue por unidad de prueba. esto significa una prueba fácil de la lógica de visualización sin IU.
EDITAR: ¿por qué crees?
ViewModel solo tiene un único parámetro para la vista en su constructor
EDIT2:
Hay dos enfoques principales para trabajar con mvvm, primero es "Ver primero", el segundo es "Primero el modelo". Por supuesto, puede mezclar ambos y elegir el mejor enfoque para sus necesidades.