2011-02-10 1 views
14

J'ai commencé à me faire une liste de "WPF gotchas": des choses qui me dérangent et que j'ai dû écrire pour me souvenir parce que je tombe amoureux d'eux à chaque fois ....Quel est le pire piège dans WPF?

Maintenant, je suis À peu près sûr, vous êtes tombé sur des situations similaires à un moment donné, et je voudrais que vous partagiez votre expérience sur le sujet:

Quel est le gotcha qui vous obtient tout le temps? celui que vous trouvez le plus ennuyeux?

(j'ai quelques questions qui semblent être sans explication, peut-être vos soumissions seront les expliquer)

Voici quelques-unes de mes gotchas « Editeur » (au hasard présentés):

  1. Pour qu'un événement MouseEvent soit déclenché même lorsque le clic est sur l'arrière-plan "transparent" d'un contrôle (par exemple une étiquette) et pas seulement sur le contenu (le texte dans ce cas), l'arrière-plan du contrôle doit être défini sur "Pinceaux". .Transparent "et pas seulement" null "(valeur par défaut pour une étiquette)

  2. Un DataContext de WPF DataGridCell est le RowView auquel la cellule appartient, pas Cellview

  3. Lorsque dans un ScrollViewer, une barre de défilement est géré par le ScrollViewer lui-même (à savoir la définition des propriétés telles que ScrollBar.Value est sans effet)

  4. Key.F10 ne se déclenche pas lorsque vous appuyez sur « F10 », au lieu que vous obtenez Key.System et vous devez aller chercher e.SystemKey pour obtenir le Key.F10

... et maintenant vous êtes sur.

+0

Ce n'est pas vraiment une question et ne convient donc pas à un site de questions et réponses. Vous demandez une «liste de X» et il n'y a pas de réponse plus exacte que toutes les autres. – ChrisF

+3

@ChrisF: Sous la forme d'une question ... "Quels sont les getchas WPF?" puis marquez-le en tant que wiki de communauté. Nous avons beaucoup de ces types de questions. –

+3

@emddudley - a) seuls les modérateurs peuvent faire des questions CW maintenant et b) c'est toujours une question de "liste de x" et c) les règles ont été resserrées puisque la plupart (sinon toutes) de ces questions ont été posées. – ChrisF

Répondre

7

1) Celui qui me recevait toutes les demi-heures lorsque je passais de WinForms: utilisez TextBlock instead of Label lorsque vous mettez du texte au hasard sur l'interface utilisateur (ou n'utilisez pas de balise, si le texte est statique)!

2) DataTriggers/Triggers ne peuvent pas être mis en Control.Triggers, mais doivent aller dans Control.Styles/style/Style.Triggers

3) Type de propriété doit mettre en œuvre IList, non IList<T>, si le La propriété doit être reconnue par XAML comme une propriété de collection.

4) Les liaisons capturent les exceptions.

5) Utilisez des convertisseurs singleton/classe de convertisseur statique, donc vous n'avez pas besoin de créer un nouveau convertisseur chaque fois que vous l'utilisez.

6) Un type de valeur par défaut de DependencyProperty doit être clairement spécifiée: 0u comme uint, (float) 0 comme flotteur, 0.0 que le double ...

7) It matters if the control's property definitions are before or after its content.

8) NE JAMAIS utiliser PropertyMetadata pour définir une valeur par défaut du type de référence DependencyProperty. La même référence d'objet sera affectée à toutes les instances de la classe propriétaire.

+0

ne connaissait pas le 2 & 3, gentils ... – David

13
  1. Toujours regarder la fenêtre de sortie pour les erreurs de liaison . Ignorer la fenêtre de sortie est une recette pour les larmes.

  2. Utilisez PresentationTraceOptions.TraceLevel = "High" dans une liaison pour obtenir des informations de liaison détaillées lors du débogage des échecs de liaison.

  3. Faire des ressources statiques, immuables tels que des brosses PresentationOptions: Gel = « true » pour sauvegarder les ressources à l'exécution.

  4. Utilisez le DataGrid WPF comme DataGrid. Le modifier pour se comporter comme Excel est une énorme douleur dans la crosse.

  5. BindingList<T> ne joue pas bien avec CollectionViewSource. Exposer ObservableCollection<T> à partir de votre viewmodels à la place.

  6. Les fournitures internet une demi-douzaine d'idées différentes pour l'affichage du texte CueBanner dans une zone de texte WPF. Ils sont tous brisés.

+0

+1 pour le premier (mettrait +2 si je pouvais :)). Je ne connaissais pas du tout le second. très intéressant, même si ce n'est pas vraiment un gotcha. + 1 aussi pour les 4 ... (Je suis juste en train de le faire: /) – David

+0

@David: Oui, moi aussi. C'est un exercice de lutte constante contre l'implément de DataGrid pour la mise au point du clavier. –

+0

Fenêtre de sortie peut être une bouée de sauvetage massive en cas de problèmes avec les liaisons. –

1

Je suis une jolie chouette une la semaine dernière:

Lorsque Templating RichTextBox, la gestion des événements à l'intérieur du modèle suit une route étrange qui n'a rien à voir ni avec tunnel, ni bouillonnant

Par exemple: dans le cas d'un événement supposé tunnel: l'événement passe d'abord par le ContentPresenter, puis il effectue un retour en arrière à partir du haut du modèle.

voir my question on the subject

2

info-bulles et ContextMenus ne partage pas le DataContext de son propriétaire? Je pense que tout le monde obtient d'abord

0

Mon préféré est celui-ci:

public double MyVariable 
{ 
    get { return (double)GetValue(MyVariableProperty); } 
    set { SetValue(MyVariableProperty, value); } 
} 
public static readonly DependencyProperty MyVariableProperty = DependencyProperty.Register(
    "MyVariable", typeof(double), typeof(MyControl), new UIPropertyMetadata(0)); 

Essayez, une fois que cette propriété est déclarée il va se planter. Pourquoi? Parce que 0 ne peut pas être affecté à un double en utilisant la réflexion apparemment.

Pas vraiment un Gotcha mais un conseil: Utilisez Snoop ou quelque chose de similaire, si vous ne l'utilisez pas vous devez être fou ... fou je vous le dis!

1

Il n'y a aucun moyen propre pour gérer la validation en WPF, je ne suis pas fan de chaîne magique qui IDataErrorInfo offre par défaut:

public string this[string columnName] 
    { 
     if (columnName == "FirstName") 
     { 
      if (string.IsNullOrEmpty(FirstName)) 
       result = "Please enter a First Name"; 
     } 
    } 

Cependant, j'ai essayé beaucoup de cadres comme SimpleMVVM, FluentValidation et MVVMValidation et LOIN MVVM la validation est le meilleur d'apprendre à faire des choses comme:

Validator.AddRule(() => RangeStart, 
      () => RangeEnd, 
      () => RuleResult.Assert(RangeEnd > RangeStart, "RangeEnd must be grater than RangeStart"); 
+0

Pas propre construit de façon - je n'appellerais pas cela un gotcha.Rappelez-vous, l'ensemble de XAML et le support de liaison est juste un tas de «chaînes magiques», de réflexion et d'expressions en cache. Vous pouvez très bien extraire les noms de propriété à partir des expressions http://stackoverflow.com/a/672212/286976 et dans .net 4.5, vous pouvez utiliser '[CallerMemberName]' https://msdn.microsoft.com/fr-fr/library /system.runtime.compilerservices.callermembernameattribute%28v=vs.110%29.aspx – Gusdor

+0

'INotifyDataErrorInfo' est également une interface beaucoup plus propre à implémenter pour WPF. – Gusdor

0

Binding.StringFormat ne fonctionne que si le type de la propriété cible est string.

2
  • Si elle est activée, Button.IsCancel attribue false-Window.DialogResult mais Button.IsDefault pas.
    Ils sont si semblables et pour moi, il semblait intuitif au début que les deux devraient fermer le dialogue. Je casse habituellement MVVM et résoudre ce problème en ne fermerons pas le code-behind

  • Button.IsCancel + Command = Dialog (Window.DialogResult gauche non affectée) mais Command EXÉCUTE
    Comme je le comprends: Si IsCancel avait une priorité plus élevée que Command puis Esc il attribuerait «faux» à DialogResult et Command ne sera pas appelé. Ou, si Command aurait une priorité plus élevée alors il serait appelé en premier et DialogResult serait attribué. Je ne comprends pas comment il est ignoré?

  • La liaison avale des exceptions! Cela non seulement vole le temps pendant le débogage, mais aussi du point de vue de la POO, car si une exception est déclenchée, quelque chose d'exceptionnel s'est produit quelque part dans notre système (de l'accès non autorisé à l'accès non autorisé à la mémoire). peut être manipulé seulement si vous savez quoi faire. Vous ne pouvez pas simplement les attraper tous, puis les ignorer. S'il y a exception inconnue dans le programme, il doit en informer l'utilisateur, connectez-vous et fermez pas faire comme si tout est ok ...

  • HeaderContent peut avoir qu'un seul contrôle enfant et n'a pas de rembourrage
    Tout doit avoir padding même des contrôles logiques (conteneurs), non? Je pense que c'est incohérent. Qu'est-ce que tu penses?

  • Si vous réglez à se concentrer ListBox via FocusManager.FocusedElement vous toujours pas être en mesure de changer son contenu avec clavier parce que l'accent est réglé sur ListBox es cadre pas son contenu. Je pense que je ne connais pas d'autres API qui exposeraient quelque chose comme des cadres de contrôles à un programmeur d'interface utilisateur, il devrait être encapsulé parce que ListBox représente une liste, c'est juste une liste de choses pas une liste de choses dans une boîte. ok il a une boîte dans son nom mais toujours ... Nous avons presque deux contrôles différents ici. MVVM not breaking fix

  • ListBox.IsSynchronizedWithCurrentItem par défaut est false donc si vous attribuer une valeur différente ou null à ItesSource puis SelectedItem tient toujours ancienne valeur jusqu'à ce que l'utilisateur sélectionne quelque chose d'une nouvelle liste. Il pourrait gâcher CanExecute par exemple. Besoin de le régler chaque fois à la main.

  • Aucune liaison exposée dans PasswordBox résultats en perte de temps et hacks sales ... Mais encore il a une propriété de chaîne PasswordBox.Password exposée alors ne même pas essayer d'argumenter sur la sécurité parce que Snoop ...

  • Ce n'est pas un gotcha mais la disposition des tables est donc IE6 IMO. La conception de conteneur aide à séparer le contenu de sa mise en page.
    Parce que chaque fois que j'ai besoin de changer quelque chose dans des endroits, j'ai besoin de gâcher avec Grid.Row et Grid.Column. Oui, nous avons DockPanel, StackPanel et d'autres mais vous ne pouvez pas faire un peu d'alignement de colonne à l'intérieur d'eux. (Et DockPanel est comme gotcha complètement séparé) Si UniformGrid serait plus personnalisable ce serait idéal je pense. Vous devez toujours choisir entre la grille et les panneaux et généralement si vous gagnez quelque chose, vous perdez autre chose.

+0

Vous ne cassez pas MVVM en fermant votre fenêtre dans le code-behind. Si votre vue a été remplacée par une page HTML, vous redirigerez au lieu de fermer la fenêtre. Le code à fermer/rediriger appartient à la vue, pas au modèle. MVVM! = Pas de code derrière – Maxence

Questions connexes