Comment implémenter correctement Indicateur de WPF Étendu Toolkit
Ok, j'ai été aux prises avec ce problème depuis un certain temps et avoir lu l'article après l'article tente de se faire une idée sur la question. Je suis en train de mettre en œuvre le Voyant d'activité et ne suis que partiellement réussi. J'ai une Coquille vue que j'ai enveloppé avec le BusyIndicator comme suit:
<Window x:Class="Foundation.Shell"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:Library.Controls.Views;assembly=Library"
xmlns:l="clr-namespace:Library.StaticClasses"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
Name="ShellView"
Style="{StaticResource BusyWindowStyle}"
SourceInitialized="Window_SourceInitialized"
DataContext="{StaticResource ShellVM}">
<xctk:BusyIndicator x:Name="ShellBusyIndicator" IsBusy="{Binding IsBusy}" DisplayAfter="0">
<Grid>
<!--Content Here -->
</Grid>
</xctk:BusyIndicator>
Suivant le modèle MVVM, j'ai un ShellViewModel qui ressemble à ceci:
public class ShellViewModel : ViewModelBase
{
#region constructor(s)
public ShellViewModel()
{
StateManager.IsBusyChange += new StateManager.IsBusyHandler(IsBusyEventAction);
}
#endregion constructor(s)
#region properties
private bool _IsBusy;
public bool IsBusy
{
get
{
return _IsBusy;
}
set
{
if (_IsBusy != value)
{
_IsBusy = value;
OnPropertyChanged("IsBusy");
}
}
}
private string _IsBusyMessage;
public string IsBusyMessage
{
get
{
return _IsBusyMessage;
}
set
{
if (_IsBusyMessage != value)
{
_IsBusyMessage = value;
OnPropertyChanged("IsBusyMessage");
}
}
}
#endregion properties
#region actions, functions, and methods
private void IsBusyEventAction(object sender, EventArgs e)
{
if (StateManager.IsBusy)
{
this.IsBusy = true;
this.IsBusyMessage = StateManager.IsBusyMessage;
}
else
{
this.IsBusy = false;
}
}
#endregion actions, functions, and methods
}
Prochaine, je suis en utilisant une classe statique appelé StateManager que je peux appeler de n'importe où qui va déclencher le voyant d'activité:
public static class StateManager
{
public static String IsBusyMessage { get; set; }
public static void IsBusyProcess(Action action)
{
IsBusyProcess(action, "Processing...");
}
public static void IsBusyProcess(Action action, String isBusyMessage)
{
IsBusyMessage = isBusyMessage;
IsBusy = true;
Application.Current.Dispatcher.Invoke(action, System.Windows.Threading.DispatcherPriority.Background);
IsBusy = false;
}
private static bool _IsBusy;
public static bool IsBusy
{
get
{
return _IsBusy;
}
set
{
if (_IsBusy != value)
{
_IsBusy = value;
IsBusyChange(null, null);
}
}
}
public delegate void IsBusyHandler(object sender, EventArgs e);
public static event IsBusyHandler IsBusyChange;
}
Enfin, je suis le déclenchement de l'indicateur dans le code comme ceci:
StateManager.IsBusyProcess(() =>
{
this.Validate();
if (!HasValidationErrors)
{
if (this.CustomerControlVM.SaveCustomer() != 0)
{
VehicleControlVM.VehicleModel.CustomerID = this.CustomerControlVM.CustomerModel.CustomerID;
this.VehicleControlVM.SaveVehicle();
ComplaintsView complaintsControl = new ComplaintsView();
(complaintsControl.DataContext as ComplaintsViewModel).CurrentVehicle = this.VehicleControlVM.VehicleModel;
(complaintsControl.DataContext as ComplaintsViewModel).CurrentCustomer = this.CustomerControlVM.CustomerModel;
StateManager.LoadView(complaintsControl, PageTransitionType.SlideLeft);
}
}
StateManager.IsBusy = false;
});
Pour résumer, le StateManager peut être appelée à partir de n'importe où dans l'application. Lorsque le StateManager.IsBusy propriété est modifiée, un événement, qui est pris dans le ShellViewModel, est déclenché. Lorsque cela se produit, le IsBusy propriété dans le ShellViewModel est définie sur true soi-disant origine du IsBusy indicateur pour montrer. La logique fonctionne très bien dans le sens que le IsBusy dans le ShellViewModel est réglé et l'indicateur de evens montre comme prévu. Ce n'est pas le droit de travailler, c'est que l'indicateur de ne pas les animer. Simplement, il reste stagner. J'ai l'impression que c'est un problème thread mais ma compréhension de la thread de l'INTERFACE utilisateur est incliné ou je ne vois pas quelque chose qui devrait être évident pour vous. Je me rends compte de la IsBusy logique ne peut pas être sur le même thread que l'INTERFACE utilisateur, mais je pense que depuis ma logique qui se passe dans le modèle de vue, il ne devrait pas être un problème. Suis-je tort? Toutes les idées ou les pensées? Une autre chose qui pourrait être utile: j'ai eu du mal, même à obtenir l'indicateur à afficher et de créer ce post qui a été résolu: Comment mettre en œuvre voyant d'activité en application shell
- Donc, ce que d'autres processus en cours d'exécution qui auraient besoin d'un voyant d'activité, il est sur un thread séparé ainsi?
- Salut Félix. Merci pour votre réponse. Le long processus en cours d'exécution doivent être sur le même thread que l'ShellViewModel sauf si j'ai oublié quelque chose. J'ai tenté d'utiliser les Threads de la fenêtre (que je n'ai jamais utilisé avant), mais il semble indiquer que mon ShellView et ShellViewModel sont à la fois dans le thread principal. Je ne sais pas comment c'est possible donc je ne suis pas fier et je suis confiante que mon propre point de vue, encore moins.
- il y a aussi un bel article sur: c-sharpcorner.com/UploadFile/mahesh/wpf-busyindicator
Vous devez vous connecter pour publier un commentaire.
Bien, j'ai enfin l'indicateur de mise en œuvre. Il a été tout à fait la tâche ardue, mais j'ai appris un peu le long du chemin. Au moins j'ai quelque chose à montrer pour elle. Alors que je n'ai pas à comprendre pourquoi mon code ne fonctionnait pas comme je l'ai écrit, je l'ai fait savoir que j'étais en train d'exécuter l'INTERFACE utilisateur correspondantes du code de l'action qui serait certainement être un problème. Je ne suis pas sûr à 100% parce que j'ai fait un peu de re-écrire et je ne suis pas froggy assez pour revenir a mon code pour jouer avec elle. Mais, la réponse à la question et voici comment j'ai mis en place l'indicateur:
Tout d'abord, rien n'a changé, à mon avis, à l'exception de la propriété et de liaison pour IsBusy peut être retiré. J'ai fini de déménager mon abonnement d'événement à partir de la vue du modèle et dans le code-behind de la vue. De mon point de vue du code derrière ressemble à ceci:
Tout d'abord, notez que j'ai créé le BusyActionEventArgs classe qui étend la classe EventArgs. Il est placé dans mon projet de Bibliothèque qui est une dépendance de chaque projet, dans ma solution:
Dernier, mon StateManager ressemble maintenant à ceci:
Noter que j'ai créé une surcharge pour le IsBusyProcess méthode pour que je puisse envoyer personnalisé dans un Message "Occupé" si je le voudrais.
Maintenant, si je modifie le code de ma question de l'extrait de code où je me suis fait à l'aide de l'Indicateur, il ressemble à ceci:
Notez le code que j'ai retiré de l'action du champ. Ce code est le code de l'INTERFACE utilisateur et provoquera une erreur si elle est à l'intérieur de la portée.
J'espère que cela aide quelqu'un d'autre qui pourrait vouloir mettre en œuvre quelque chose de similaire ou a des problèmes. Grâce stackoverflow pour simplement exister sur celui-ci. Parfois, de parler (ou de frappe), il rend la différence.