Как отложить запрос данных в классе Silverlight ViewModel? - PullRequest
5 голосов
/ 07 декабря 2010

У меня есть приложение Silverlight с несколькими графиками и верхним элементом управления датой, который позволяет пользователю устанавливать диапазон дат (например, 1 июля - 30 сентября).

Обычно, когда пользователь изменяет диапазон дат, выполняется команда, которая устанавливает для свойства ViewModel DateRange новое значение. Сеттер DateRange вызывает метод RunQueries, который запрашивает новые данные и устанавливает свойства Data1 и Data2 с результатами этих запросов. Графики, связанные с Data1 или Data2, обновляются соответствующим образом. Ниже приведен базовый код ViewModel; обратите внимание на вызов метода RunQueries в установщике DateRange.

В настоящее время в действительности уже существует более двух сборов данных, и по мере расширения приложения они продолжают добавляться. Кроме того, не все графики видны одновременно; иногда виден только один график. Но когда пользователь изменяет диапазон дат, все запросы для получения всех данных, необходимых для любого из графиков, перезапускаются с новыми датами начала и окончания. Это кажется мне очень неэффективным - возможно, нужно выполнить только один запрос!

Итак, мой вопрос - как мне реализовать отложенные запросы данных в моем классе ViewModel?

Вот две идеи, которые я рассматривал:

  • Отслеживайте, какие коллекции данных являются актуальными, и затем проверяйте метод получения данных, нужно ли выполнять запрос.
  • Разбейте ViewModel на несколько подклассов, по одному для каждого графика, и пусть каждая ViewModel будет управлять своими собственными данными с помощью базового класса, отслеживающего DateRange.

Обе идеи кажутся сложными для реализации, и мне было интересно - есть ли стандартный подход к этому? Я что-то упустил в шаблоне проектирования MVVM, который решает эту проблему?


Вот очень упрощенная версия моего класса 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
}

1 Ответ

1 голос
/ 08 декабря 2010

Я постараюсь обобщить вашу ситуацию:

  • Если диапазон данных изменяется - обновляются только видимые графики.
  • Если какой-либо график становится видимым - он должен обновляться самнемедленно.

Таким образом, существует очевидная потребность в свойстве видимости.

Решение по 1-му пункту: проверьте возможность выполнения команды в методе RunQueries.

Решениедля 2-й точки: выполнить команду в наборе свойства Visibility.

Вот пример:

private DelegateCommand UpdateData1Command { get; set; }

    public MyViewModel()
    {
        this.UpdateData1Command = new DelegateCommand(_ => this.GetData1(), _ => this.IsGraph1Visible);
    }

    private bool isGraph1Visible;

    public bool IsGraph1Visible
    {
        get { return isGraph1Visible; }
        set
        {
            isGraph1Visible = value;
            OnPropertyChanged("IsGraph1Visible");

            if(UpdateData1Command.CanExecute(null))
                UpdateData1Command.Execute(null);
        }
    }

    private void RunQueries()
    {
        if (UpdateData1Command.CanExecute(null))
            UpdateData1Command.Execute(null);
    }

    private void GetData1()
    {
        // call wcf service to get the data
    }

Теперь у каждого графа есть свойства Data, IsVisible, UpdateDataCommand и метод GetData.Я рекомендую перенести их в отдельную модель просмотра.

...