Данные веб-службы MVVM как во время разработки, так и во время выполнения - PullRequest
0 голосов
/ 01 февраля 2011

Я недавно смотрел Шаблоны обслуживания Джона Папы с SL из SL Firestarter 2010 , в которых описан шаблон сервиса в MVVM Light, который я сейчас пытаюсь реализовать. Я опишу процесс ниже, но хотел бы сначала заявить, что я смог получить данные «времени разработки» без проблем. То, что я не могу понять, это мои данные во время выполнения. К сожалению, мой клиент застрял с помощью веб-служб .asmx старой школы, и мои руки связаны с этим.

Из моей ViewModel я вызываю IAccountService, интерфейс, который я настроил с помощью моего единственного метода: GetAccounts. Отсюда я использую класс ServiceProviderBase, чтобы определить, поступил ли вызов во время разработки или во время выполнения. Когда я вызываю этот метод во время разработки, я загружаю DesignAccountService, который использует модель DesignAccount для заполнения поддельных данных, которые в конечном итоге отображаются в моем Gridview. Это работает, я в восторге.

Когда я вызываю метод GetAccounts из среды выполнения,. Парень из БД здесь написал и протестировал веб-сервис, который возвращает данные в таблицу данных, а затем преобразует их в ObservableCollection. Этот веб-сервис работает внутри веб-проекта решения. Я пытаюсь вызвать этот веб-сервис из моего проекта SL и получить наблюдаемую коллекцию ... Хорошо, так что код:

В моей ViewModel:

    protected TSMVVM.Services.IAccountService AccountService { get; set; }

    public AccountDefinitionViewModel(TSMVVM.Services.IAccountService accountService)
    {
        AccountService = accountService;
        LoadData();
    }
    public void LoadData()
    {
        LoadAccounts();
    }
    public void LoadAccounts()
    {
        Accounts = null;
        AccountService.GetAccounts(GetAccountsCallback);
    }
    private void GetAccountsCallback(ObservableCollection<TSMVVM.Model.P.P_ACCOUNTS> accounts)
    {
        if (accounts != null)
        {
            this._accounts = accounts;
            if (_accounts.Count > 0)
            {
                SelectedAccount = Accounts[0];
            }
        }
    }
    private ObservableCollection<TSMVVM.Model.P.P_ACCOUNTS> _accounts;
    public ObservableCollection<TSMVVM.Model.P.P_ACCOUNTS> Accounts
    {
        get { return _accounts; }
        set
        {
            _accounts = value;
            RaisePropertyChanged("Accounts");
        }
    }

Интерфейс:

public interface IAccountService
{   
    void GetAccounts(Action<ObservableCollection<TSMVVM.Model.P.P_ACCOUNTS>> getAccountsCallback);
}

AccountService

        private ObservableCollection<TSMVVMCommonSVC.TSAccount> _account = new ObservableCollection<TSMVVMCommonSVC.TSAccount>();
    private TSMVVMCommonSVC.CommonSoapClient CommonService;
    private Action<ObservableCollection<TSMVVMCommonSVC.TSAccount>> _getAccountsCallback;

    public AccountService()
    {
    }
    public void GetAccounts(Action<ObservableCollection<TSMVVM.Model.P.P_ACCOUNTS>> getAccountsCallback)
    {
        _getAccountsCallback = getAccountsCallback;
        Uri iSilverlightServiceUriRelative = new Uri(App.Current.Host.Source, "../Services/Common.asmx");
        EndpointAddress iSilverlightServiceEndpoint = new EndpointAddress(iSilverlightServiceUriRelative);
        BasicHttpBinding iSilverlightServiceBinding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);// Transport if it's HTTPS://
        CommonService = new TSMVVMCommonSVC.CommonSoapClient(iSilverlightServiceBinding, iSilverlightServiceEndpoint);
        CommonService.GetAccountCollectionCompleted +=new EventHandler<TSMVVMCommonSVC.GetAccountCollectionCompletedEventArgs>(CommonService_GetAccountCollectionCompleted);
        CommonService.GetAccountCollectionAsync();
    }
    private void CommonService_GetAccountCollectionCompleted(object sender,TSMVVMCommonSVC.GetAccountCollectionCompletedEventArgs e)
    {
        if (e.Result.Length > 0)
        {
            foreach (TSMVVMCommonSVC.TSAccount item in e.Result) {
                var acct = new TSMVVM.Model.P.P_ACCOUNTS() {
                     ACCOUNT_NUMBER = item.AccountNumber,
                     DESCRIPTION = item.AccountDescription
                };
                _account.Add(acct);
            }
        }
        _getAccountsCallback(_account);
    }

Теперь, если я поставлю точку останова в моей ViewModel на GET для учетных записей (которая должна возвращать _accounts), для учетных записей будет настроена коллекция элементов с 315 элементами в ней. Если я углублюсь в эту коллекцию, то увижу, что данные успешно возвращены из моего веб-сервиса. Фактически, в этот момент останова, если я вхожу в свой xaml (код работает практически одинаково в DataGrid вместо элемента управления telerik),

        <telerik:RadGridView ItemsSource="{Binding Accounts}"
                                SelectedItem="{Binding SelectedAccount, Mode=TwoWay}"
                                AutoGenerateColumns="False">
        <telerik:RadGridView.Columns>
            <telerik:GridViewDataColumn DataMemberBinding="{Binding Path=ACCOUNT_NUMBER}" Header="Account Number" />
            <telerik:GridViewDataColumn DataMemberBinding="{Binding Path=DESCRIPTION}" Header="Description" />
        </telerik:RadGridView.Columns>

    </telerik:RadGridView>

С установленной точкой останова я вижу, что переменная Accounts в моей привязке ItemsSource установлена ​​на эту коллекцию из 315 элементов. Однако сетка пуста. Я знаю, что мои привязки столбцов привязаны к правильным элементам, но я не могу понять, куда идти дальше.

1 Ответ

2 голосов
/ 01 февраля 2011

Изменить этот код:

    if (accounts != null)
    {
        this._accounts = accounts;

с

    if (accounts != null)
    {
        this.Accounts = accounts;

Поскольку событие PropertyChanged не запускается в первом коде, а пользовательский интерфейс ничего не знает об изменениях.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...