2010-12-10 41 views
0

我有一个数据网格(称为dat1),它有一个项目源绑定到一个自定义类型的可观察集合,称之为TypeA。 TypeA上的其中一个属性是另一个自定义类型的可观察集合,称为TypeB。然后我有一个组合框,绑定到dat1的SelectedItem.TypeB。什么是导致我的WPF组合框项目花费这么长时间来刷新itemssource时更改?

因此,当用户在dat1中选择TypeA时,组合框将显示来自所选TypeA的TypeB可观察集合中的项目。合理?

该绑定能工作,它会更新。问题是,当组合框中的项目演示者已经显示项目并且用户在dat1中选择了不同的TypeA并尝试查看组合框中的新项目时,项目演示者生成新项目时会有很长的暂停。

为了测试这个问题,我可以简化这个场景。

重现步骤:

  1. 创建使用.NET 4.0一个新的WPF项目。

  2. 剪下并粘贴下面的代码。

  3. 要获得冻结行为,必须放下组合框以查看项目,然后单击该按钮,以便项目源更改,然后再次放下组合框。几秒钟后组合框下降,但为什么这么慢?

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> 

代码

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; } 
} 

注意:这是一个WPF问题。我听说Silverlight没有相同的问题。我不需要知道Silverlight是否有效。我需要一个WPF答案。

PS。当项目源更改为junk2时,延迟时间会更长,可能是因为它较大。

它足够延迟,我认为它可能是由绑定异常引起的,因为异常需要时间。有没有办法查看是否存在绑定异常?

+0

你应该看到在VS IDE输出窗口绑定例外,而调试。 – VoodooChild 2010-12-10 02:13:10

+0

我没有看到您发布的代码有太长时间的停顿。 – lesscode 2010-12-10 02:25:16

回答

0

我也观察过这种现象。 我在Windows 7 x64上使用Visual Studio 2010(使用ReSharper 6.0)。

上面的例子中只有四个项目并不明显,但如果我让它例如50个或更多的项目冻结非常明显。 重新绑定后,它会挂起大约15秒,然后我才能再次与之互动。

另一个有趣的事情是,这只发生在调试VS.如果我单独运行exe文件,它真的很快速。

这里是我的简单的项目代码:

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> 

代码

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; } 
    } 
} 

我会再次张贴在这里,如果我找到一个解决方案或替代方法这一点。

相关问题