2010-12-10 48 views
0

J'ai une grille de données (appelez-la dat1) qui a une source d'éléments liée à une collection observable d'un type personnalisé, appelez-la TypeA. L'une des propriétés de TypeA est une collection observable d'un autre type personnalisé, appelez-la TypeB. J'ai alors une liste déroulante avec une source d'éléments liée à SelectedItem.TypeB de dat1. Par conséquent, lorsque l'utilisateur sélectionne un TypeA dans dat1, la zone de liste déroulante affiche les éléments de la collection observable TypeB provenant du type A sélectionné. Avoir du sens?Qu'est-ce qui cause que mes éléments de liste déroulante WPF prennent tellement de temps à s'actualiser lorsque la source d'éléments est modifiée?

La liaison fonctionne et elle est mise à jour. Le problème est que lorsque le présentateur d'éléments dans la liste déroulante a déjà affiché des éléments et que l'utilisateur sélectionne un TypeA différent dans dat1 et tente d'afficher les nouveaux éléments dans la liste déroulante, il y a une longue pause pendant que le présentateur génère les nouveaux éléments.

Pour tester le problème, je peux simplifier le scénario.

Étapes pour reproduire:

  1. Créer un nouveau projet WPF en utilisant .NET 4.0.

  2. Coupez et collez le code ci-dessous. Pour obtenir le comportement de congélation, vous devez supprimer la liste déroulante pour voir les éléments, puis cliquez sur le bouton pour modifier la source des éléments, puis relâchez la liste déroulante. La combobox tombe après quelques secondes, mais pourquoi si lent?

XAML

<Window x:Class="ComboBoxTest.MainWindow" 
     xmlns:System="clr-namespace:System;assembly=mscorlib" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <StackPanel> 
      <ComboBox x:Name="cbo" DisplayMemberPath="Junk1"></ComboBox> 
      <Button Content="Click Me!" Click="btn_Click"></Button> 
     </StackPanel> 
    </Grid> 
</Window> 

code

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     this.cbo.ItemsSource = junk1; 
    } 

    ObservableCollection<Junk> junk1 = new ObservableCollection<Junk>() { 
     new Junk() { Junk1 = "junk1 - 1" }, 
     new Junk() { Junk1 = "junk1 - 2" } }; 

    ObservableCollection<Junk> junk2 = new ObservableCollection<Junk>() { 
     new Junk() { Junk1 = "junk2 - 1" }, 
     new Junk() { Junk1 = "junk2 - 2" }, 
     new Junk() { Junk1 = "junk2 - 3" }, 
     new Junk() { Junk1 = "junk2 - 4" } }; 

    private void btn_Click(object sender, RoutedEventArgs e) 
    { 
     if (this.cbo.ItemsSource == junk1) 
      this.cbo.ItemsSource = junk2; 
     else 
      this.cbo.ItemsSource = junk1; 
    } 
} 

public class Junk 
{ 
    public string Junk1 { get; set; } 
} 

NOTE: Ceci est un problème WPF. J'ai entendu dire que Silverlight n'a pas le même problème. Je n'ai pas besoin de savoir si Silverlight fonctionne. J'ai besoin d'une réponse WPF.

PS. Le délai est plus long lorsque la source des éléments est modifiée en indésirable2, vraisemblablement parce qu'elle est plus grande.

Cela retarde assez que je pense qu'il peut être provoqué par des exceptions de liaison, puisque les exceptions prennent du temps. Existe-t-il un moyen de voir si des exceptions obligatoires sont levées?

+0

Vous devriez voir les exceptions de liaison dans la fenêtre de sortie dans VS IDE, pendant le débogage. – VoodooChild

+0

Je ne vois pas de longue pause avec le code que vous avez posté. – lesscode

+0

De même ici, il semble n'y avoir aucune hésitation. –

Répondre

0

J'observe aussi ce phénomène. J'utilise Visual Studio 2010 (avec ReSharper 6.0) sous Windows 7 x64.

Il n'est pas perceptible avec seulement quatre éléments comme dans l'exemple ci-dessus, mais si je le fais par ex. 50 ou plus d'articles le gel devient très perceptible. Après la reliaison, il sera suspendu pendant environ 15 secondes avant que je puisse à nouveau interagir avec lui.

Une autre chose intéressante est que cela ne se produit que lors du débogage dans VS. Si je cours l'exe standalone c'est vraiment rapide et rapide.

Voici le code de mon projet simple:

XAML

<Window x:Class="ComboBoxFreeze.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 
    <StackPanel> 
    <ComboBox x:Name="cbo" DisplayMemberPath="Junk1"></ComboBox> 
    <Button Content="Click Me!" Click="btn_Click"></Button> 
    </StackPanel> 
</Window> 

code

using System.Collections.ObjectModel; 
using System.Windows; 

namespace ComboBoxFreeze 
{ 
    public partial class MainWindow 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
      Loaded += MainWindow_Loaded; 

      _junk1 = new ObservableCollection<Junk>(); 
      for (int i = 0; i < 50; i++) 
      { 
       _junk1.Add(new Junk { Junk1 = "Prop1a-" + i, Junk2 = "Prop1b-" + i }); 
      } 


      _junk2 = new ObservableCollection<Junk>(); 
      for (int i = 0; i < 50; i++) 
      { 
       _junk2.Add(new Junk { Junk1 = "Prop2a-" + i, Junk2 = "Prop2b-" + i }); 
      } 
     } 

     private readonly ObservableCollection<Junk> _junk1; 

     private readonly ObservableCollection<Junk> _junk2; 

     void MainWindow_Loaded(object sender, RoutedEventArgs e) 
     { 
      cbo.ItemsSource = _junk1; 
     } 

     private void btn_Click(object sender, RoutedEventArgs e) 
     { 
      if (cbo.ItemsSource == _junk1) 
      { 
       cbo.ItemsSource = _junk2; 
      } 
      else 
      { 
       cbo.ItemsSource = _junk1; 
      } 
     } 
    } 

    public class Junk 
    { 
     public string Junk1 { get; set; } 
     public string Junk2 { get; set; } 
    } 
} 

Je vais poster ici si je trouve une solution ou solution de contournement à ce sujet.

+0

En cours d'exécution sur mon ordinateur portable dans VS2008, Win7 x64, Resharper 5.1, ce code est très accrocheur. Pas de problèmes d'hésitation ici. Je me demande si cela vaut la peine d'afficher la sortie de débogage complète lors de l'exécution sur votre machine. Peut-être que l'examen des versions d'assemblage en cours de chargement pourrait fournir un aperçu. – RMart