Je suis relativement nouveau sur MVVM et j'essaye de coder une barre d'état de base pour une application MVVM WPF. Je pense avoir le sens des choses, mais pour une raison quelconque, la barre d'état ne se met pas toujours à jour, et je ne sais pas pourquoi.StatusBar ne met pas toujours à jour
Dans mon ViewModel, j'ai une propriété de base que je mets à jour lorsque je change un message d'état:
public string StatusMessage
{
get { return _statusMessage; }
set
{
if (value == _statusMessage) return;
_statusMessage = value;
base.OnPropertyChanged(() => this.StatusMessage);
}
}
Ma méthode OnPropertyChanged (que j'ai dans une classe ViewModel de base qui implémente INotifyPropertyChanged) ressemble à ceci (eu cette idée de Gunther Foidl, souhaite que je pourrais demander un crédit pour cela parce que je pense qu'il est lisse mais je ne suis pas tout à fait aussi intelligent):
protected virtual void OnPropertyChanged<T>(Expression<Func<T>> exp)
{
MemberExpression me = exp.Body as MemberExpression;
string propName = me.Member.Name;
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propName));
}
}
en tout cas, tout cela fonctionne très bien pour tous mes contrôles sauf un. Sur mon fichier MainWindow.xaml, j'ai un contrôle StatusBarItem lié à la propriété ci-dessus, comme si (le reste du XAML a été coupé pour des raisons d'espace):
<StatusBarItem Grid.Column="0">
<TextBlock TextTrimming="CharacterEllipsis" Text="{Binding Path=StatusMessage}" />
</StatusBarItem>
Quand je lance mon application (qui frappe un deux DB en plus de générer un document à partir d'un modèle et un tas d'autres choses assez gourmandes en ressources), certains messages, mais pas tous, s'affichent dans la barre d'état. J'ai débogué et vérifié que les messages le font tous dans la propriété StatusMessage, ci-dessus (et la variable privée qui en découle), ils ne semblent tout simplement pas rafraîchir dans l'interface utilisateur.
J'ai regardé plusieurs exemples qui utilisent des instances BackgroundWorker pour les contrôles ProgressBar, mais n'en ont vu aucun pour les contrôles StatusBarItem, et je ne suis pas vraiment sûr de savoir comment traduire les uns vers les autres. J'ai également utilisé des tâches auparavant dans les applications précédentes C# 4.0 et WPF, et je me dis que c'est probablement un bon moyen d'y aller, mais je n'ai pas vraiment été capable de comprendre comment/où désigner la tâche de l'interface utilisateur (I ' Je l'ai toujours fait dans le code-behind pour MainWindow avant, mais je cherche un code-zéro pour rester en accord avec MVVM ici). Je suis à peu près sûr qu'une approche multi-thread est la voie à suivre; Je n'en sais pas assez sur une approche (j'en connais un peu et un peu de ça) pour que ça marche. J'ai vu quelques messages qui utilisaient l'ancienne approche de threading directement, mais je suis resté à l'écart de la programmation multithread jusqu'à ce que je commence à utiliser Tasks avec .NET 4.0 (les trouvant un peu plus faciles à comprendre et à suivre), alors j'avais un peu de difficulté à les comprendre.
Quelqu'un peut-il avoir pitié de moi et me diriger dans la bonne direction, ou suggérer un débogage supplémentaire que je peux faire? Merci!
J'ai une mise à jour similaire à un problème TextBlock, avez-vous trouvé une solution à la fin? –
Je pouvais ** faire fonctionner le code de la tâche, en passant mon TaskScheduler de l'interface utilisateur dans mon ViewModel et en effectuant la mise à jour sur une tâche engendrée par ledit planificateur. Je posterai des exemples de code dans une réponse séparée, si le temps le permet. –
@Julien, voici ce que j'ai fait. Lors de l'initialisation de mon ViewModel dans mon fichier App.xaml.cs, j'ai transmis 2 instances de TaskFactory: Une pour l'interface utilisateur: 'new TaskFactory (TaskScheduler.FromCurrentSynchronizationContext())' que j'ai appelé 'UiTasks', et un pour tout le reste' Tâche .Factory' que j'ai appelé 'DefaultTasks'. Ensuite, je me suis assuré que mon gros travail s'exécutait sous la fabrique de tâches par défaut, et mis à jour ma propriété en utilisant l'interface utilisateur: 'this.UiTasks.StartNew (() => this.StatusMessage = myMessage;});' Cela semblait faire l'affaire . Je serai heureux de vous envoyer un exemple plus détaillé si vous le souhaitez. Bonne chance! –