Tengo una aplicación Silverlight con varios gráficos y un control de fecha en la parte superior que permite al usuario establecer el intervalo de fechas (por ejemplo, del 1 de julio al 30 de septiembre).Cómo aplazar la consulta de datos en la clase Silverlight ViewModel?
Básicamente, cuando un usuario modifica el rango de fechas, se ejecuta un comando que establece la propiedad DateRange
de ViewModel en el nuevo valor. El programador DateRange
llama al método RunQueries
que consulta los datos nuevos y establece las propiedades Data1
y Data2
con los resultados de esas consultas. Los gráficos que están limitados a Data1
o Data2
se actualizan en consecuencia. Vea a continuación el código básico de ViewModel; tome nota de la llamada al método RunQueries
en el setter DateRange
.
Ahora, en realidad, ya se han agregado más de dos colecciones de datos y más a medida que se amplía la aplicación. Además, no todos los gráficos son visibles a la vez; a veces, solo un gráfico es visible. Pero cuando el usuario cambia el intervalo de fechas, todas las consultas para obtener todos los datos que se necesitan para cualquiera de los gráficos se vuelven a ejecutar con las nuevas fechas de inicio y finalización. Esto me parece muy ineficiente, ¡quizás solo se necesite ejecutar una consulta!
Así que mi pregunta es: ¿cómo implemento la consulta de datos diferidos en mi clase ViewModel?
Éstos son dos ideas que he estado considerando: pista
- Mantener las cuales las colecciones de datos están al día y después comprobar en el método de obtención de datos si una consulta necesita ser ejecutado.
- Divida el ViewModel en varias subclases, una para cada gráfico, y haga que cada ViewModel administre sus propios datos con la clase base manteniendo un registro del DateRange.
Ambas ideas parecen complejas de implementar y me he estado preguntando: ¿existe un enfoque estándar para esto? ¿Me falta algo en el patrón de diseño de MVVM que resuelve este problema?
Aquí está la versión muy simplificada de mi clase ViewModel:
public class MyViewModel: INotifyPropertyChanged
{
private ObservableCollection<MyData> _Data1;
private ObservableCollection<MyData> _Data2;
private MyDateRange _DateRange;
public ObservableCollection<MyData> Data1
{
get
{
return _Data1;
}
set
{
if (_Data1 != value)
{
_Data1 = value;
NotifyPropertyChanged("Data1");
}
}
}
// getter and setter for Data2 go here
public MyDateRange DateRange
{
get
{
return _DateRange;
}
set
{
if (_DateRange != value)
{
_DateRange = value;
NotifyPropertyChanged("DateRange");
// if date range changed, need to query for stats again
RunQueries();
}
}
}
private void RunQueries()
{
GetData1();
GetData2();
}
private void GetData1()
{
// call wcf service to get the data
}
private void GetData1Completed(object s, EventArgs e)
{
// update Data1 property with results of service call
}
// etc
}
¡Excelente respuesta y un gran diseño! No hubiera pensado en usar comandos, pero en realidad es una buena opción y hará que sea muy sencillo implementar un botón de "actualizar datos" en algún momento. ¡Gracias! – MCS
¿Cómo sugeriría usar múltiples clases de ViewModel en un caso como este en el que se deben compartir algunos de los datos (por ejemplo, DateRange)? Use la composición y haga que el ViewModel de cada gráfico contenga una referencia al ViewModel compartido. O usar algún tipo de herencia? – MCS
Sí, es necesario agregar una propiedad DateRange al otro modelo de vista. Una de las formas posibles es usar DependencyProperties en ambos viewmodels y vincular una propiedad a otra. Pero requiere una herencia de DependencyObject y puede ser inconveniente a veces. Por lo tanto, prefiero usar foreach loop dentro del setter de la propiedad MyViewModel.DateRange, algo como esto: foreach (GraphViewModel vm en this.GraphModels) vm.UpdateDateRange (value); – vorrtex