Bonjour à vous,
Je travaille actuellement sur un projet Xamarin.Forms (la chance hein ^^). Ayant travaillé majoritairement sur des projets Silverlight datant d'avant la sortie de Async Await et des Tasks.
Du coup je n'ai pas eu la chance de découvrir toutes les subtilités. Du coup, je compte sur vous pour m'aider :)
Je développe avec le patern MVVM. J'ai une classe BaseViewModel. Cette méthode contient une méthode abstraite nommée OnViewAndComponentsLoaded.
Dans chacune de mes vues, je surcharge la méthode OnAppearing qui est déclenché au chargement de l'UI (équivalent de Loaded).
Dans cette méthode, je peux être amené à faire 1 ou n appels webservice. Et c'est là que je sens mon implémentation foireuse (je me permet on est entre nous).
Exemple :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 /// <summary> /// ViewModel de base : implémente INotifyPropertyChanged et possède une propriété pour gérer le verrouillage de l'application. /// </summary> public abstract class BaseViewModel : INotifyPropertyChanged { #region - INotifyPropertyChanged - public event PropertyChangedEventHandler PropertyChanged; public void RaisePropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } #endregion private bool _IsLoading; /// <summary> /// Permet de savoir si l'application est verrouiller pour attendre un retour web service. /// Fait appel à : ServicesContainer.Instance.UserInterfaceService.Verrouillage(). /// </summary> public bool IsLoading { get { return _IsLoading; } set { _IsLoading = value; ServicesContainer.Instance.UserInterfaceService.Verrouillage(_IsLoading); } } /// <summary> /// Méthode appelée par chaque view une fois affichée. /// </summary> public abstract void OnViewAndComponentsLoaded(); }
Exemple d'une vue, une fois affichée, elle va demander au viewmodel de s'initialiser.
Et un exemple de viewmodel héritant de ma classe de base et qui surcharge la méthode OnViewAndComponentsLoaded.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 public partial class ActualitesPage { public ActualitesPage(ConnectionDataModel connectionData) { InitializeComponent(); this.BindingContext = new ActualitesViewModel(connectionData); } protected override void OnAppearing() { base.OnAppearing(); (this.BindingContext as BaseClass.BaseViewModel).OnViewAndComponentsLoaded(); } }
Le helper post que j'utilise dans le viewmodel :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 public class ActualitesViewModel : BaseViewModel { public ActualitesViewModel() { } public override async void OnViewAndComponentsLoaded() { this.IsLoading = true; string resultat = await RequestHelper.PostAsync("https://sitewebpouravoirdonnees/mobile/listeactualites", new NameValueCollection() { { "session", this._ConnectionData.NumSession }, { "numeroPage", "1" }, { "nbPerPage", "5"} }); if (!string.IsNullOrEmpty(resultat)) { var liste = ServicesContainer.Instance.SerialisationService.DeserializeCollection<ResumeActualiteModel>(resultat); this.Actualites = new ObservableCollection<ResumeActualiteModel>(); liste.ForEach((item) => { this.Actualites.Add(item); }); } this.IsLoading = false; } private ObservableCollection<ResumeActualiteModel> _Actualites; public ObservableCollection<ResumeActualiteModel> Actualites { get { return _Actualites; } set { _Actualites = value; RaisePropertyChanged("Actualites"); } } }
Pas de chance, ça ne semble pas fonctionner :( pourtant je rentre bien dans l'ajout de ligne. Précision : si le code dans la méthode est placé dans le constructeur, que je fais l'appel de façon synchrone, ma liste est bien chargée et l'UI est bien notifiée.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 public class RequestHelper { public static string Post(string uri, NameValueCollection pairs) { byte[] response = null; using (WebClient client = new WebClient()) { response = client.UploadValues(uri, pairs); } return System.Text.Encoding.UTF8.GetString(response); } public static Task<string> PostAsyncTask(string uri, NameValueCollection pairs) { return Task.Run<string>(() => Post(uri, pairs)); } public async static Task<string> PostAsync(string uri, NameValueCollection pairs) { byte[] response = null; using (WebClient client = new WebClient()) { response = await client.UploadValuesTaskAsync(uri, pairs); } return System.Text.Encoding.UTF8.GetString(response); } }
Sinon, peut être qu'en utilisant une autre façon de faire (utiliser la méthode PostAsync qui retourne une Task et changer ma méthode OnViewAndComponentsLoaded en fonction qui retourne une task.
Mais alors comment faire si jamais je n'ai pas d'appel webservice à faire mais setter des valeurs, gérer des événements ou peu importe mais sans traitement awaitable.
Je ne sais pas si c'est clair, donc n'hésitez pas à me demander d'éclaircir certains points. Je vous remercie pour votre lecture.
Bonne journée à vous tous !
Partager