2015-09-08 2 views
1

Я создаю приложение Windows Phone 8.1 с использованием шаблона MVVM и инструментария MVVM Light.Установить видимость ProgressBar из ViewModel до и после извлечения данных из службы webservice

Я пытаюсь создать простую страницу входа, которая берет имя пользователя и пароль от пользователя и проходит проверку подлинности с помощью webservice. Во время этого процесса аутентификации я хочу показать ProgressBar (загрузочные точки) в верхней части страницы, чтобы указать, что что-то происходит.

Я успешно создал свой ViewModel и связал свой просмотр, чтобы позволить мне контролировать видимость ProgressBar из команды, прикрепленной к моей кнопке входа. Это работает, однако, пользовательский интерфейс обновляется только, чтобы показать ProgressBar, как только весь процесс входа в систему завершен, что делает индикацию прогресса бессмысленной.

Как установить видимость ProgressBar (и обновить пользовательский интерфейс), а затем отключить выполнение процесса входа в систему?

Вот код:

XAML

<ProgressBar IsIndeterminate="True" Height="1" Visibility="{Binding Login.ProgressVisibility, UpdateSourceTrigger=PropertyChanged, FallbackValue=Collapsed}" /> 

ViewModel

public class LoginViewModel : ViewModelBase 
{ 
    private IDialogService dialogService; 
    private INavigationService navigationService; 

    private string _username; 
    private string _password; 

    private Visibility _progressVisibility = Visibility.Collapsed; 

    /// <summary> 
    /// User login name/email address 
    /// </summary> 
    public string Username 
    { 
     get 
     { 
      return _username; 
     } 
     set 
     { 
      Set(() => Username, ref _username, value); 
     } 
    } 

    /// <summary> 
    /// User password 
    /// </summary> 
    public string Password 
    { 
     get 
     { 
      return _password; 
     } 
     set 
     { 
      Set(() => Password, ref _password, value); 
     } 
    } 

    /// <summary> 
    /// Is loading in progress 
    /// </summary> 
    public Visibility ProgressVisibility 
    { 
     get 
     { 
      return _progressVisibility; 
     } 
     set 
     { 
      Set(() => ProgressVisibility, ref _progressVisibility, value); 
     } 
    } 

    /// <summary> 
    /// Perform login action 
    /// </summary> 
    public RelayCommand LoginCommand { get; private set; } 

    /// <summary> 
    /// constructor 
    /// </summary> 
    /// <param name="dialogService"></param> 
    public LoginViewModel(IDialogService dialogService, INavigationService navigationService) 
    { 
     this.LoginCommand = new RelayCommand(this.Login, CanLogin); 
     this.dialogService = dialogService; 
     this.navigationService = navigationService; 

    } 

    public void Login() 
    { 
     this.ProgressVisibility = Visibility.Visible; 

     //check the credentials have been provided 
     if (this._username == null || this._password == null) 
     { 
      //show dialogue 
      dialogService.ShowMessage("Please enter you login credentials", "Login"); 
     } 
     else 
     { 

      //perform an authentication request with the service 
      ValidateLoginRequest request = new ValidateLoginRequest(); 

      request.Device = new Device(); 
      request.UserName = this.Username; 
      request.Password = this.Password; 

      var response = Task.Run(() => LoginAsync(request)).GetAwaiter().GetResult(); 

      if (response != null) 
      { 
       if (response.IsSuccessful) 
       {       
        navigationService.NavigateTo("Main"); 
       } 
       else 
       { 

        dialogService.ShowMessage(response.ErrorCode + " :" + response.ErrorMessage, "Login"); 
       } 
      } 
      else 
      { 
       //failure 
       dialogService.ShowMessage("ECOM000: An unknown error has occurred", "Login"); 
      } 
     } 



    } 

    async Task<ValidateLoginResponse> LoginAsync(ValidateLoginRequest request) 
    { 
     Model.RuntimeDataService proxy = new Model.RuntimeDataService(); 
     ValidateLoginResponse response = (ValidateLoginResponse)await proxy.PostAsync(request, typeof(ValidateLoginResponse), "ValidateLogin"); 
     return response; 
    } 

    public bool CanLogin() 
    { 
     return true; 
    } 
} 

ответ

0

Вы создаете фон Task, а затем в результате чего поток пользовательского интерфейса, чтобы ждать ответа.

Попробуйте в ожидании Task вернулся из метода LoginAsync:

var response = await LoginAsync(request); 

Это должно позволить вашему потоку пользовательского интерфейса, чтобы продолжить, с остальной частью методы, действующей в качестве обратного вызова.

Возможно, вам понадобится добавить ключевое слово async в метод Login.

+0

Это сработало спасибо. Я не уверен, почему я закончил использовать Task.Run – DazzledKid

1

Я решил это, используя Котлин, добавив свой собственный CustomBindingAdapter:

@BindingAdapter("android:visibility") 
fun setVisibility(view: View, visible: Boolean) { 
view.visibility = if (visible) View.INVISIBLE else View.VISIBLE 
} 

Внутри вашего view.xml: Сначала добавьте переменную данных:

<data> 
    <variable name="loginViewModel" type="yourpackage.viewmodel.LoginViewModel"/> 
</data> 

<ProgressBar 
     android:id="@+id/login_progress_bar" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:indeterminate="true" 
     android:layout_centerHorizontal="true" 
     android:layout_centerVertical="true" 
     android:visibility="@{!loginViewModel.loginProgress}" /> 

Ваша активность должна иметь:

val binding = DataBindingUtil.setContentView<LoginViewBinding>(this, R.layout.login_view) 
val loginViewModel = LoginViewModel(this) 
binding.setLoginViewModel(loginViewModel) 

В конец вашей ViewModel необходимо обработать видимость:

var loginProgress = ObservableField<Boolean>() 
fun doSomething(){ 
     this.loginProgress.set(true) 
} 

И установите loginProgress.set(false) везде, где необходимо остановить прогресс.

Я надеюсь, что это может помочь кому-то еще;)

Смежные вопросы