什么是导致我的WPF组合框项目花费这么长时间刷新,当项目资源更改? [英] What is causing my WPF combobox items to take so long to refresh when the itemssource is changed?

查看:116
本文介绍了什么是导致我的WPF组合框项目花费这么长时间刷新,当项目资源更改?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个datagrid(称为dat1)有一个项目源绑定到一个自定义类型的observable集合,称为TypeA。 TypeA上的一个属性是另一个自定义类型的可观察集合,称为TypeB。然后我有一个组合框,其中一个项目源绑定到dat1的SelectedItem.TypeB。



所以当用户在dat1中选择一个TypeA时,组合框显示TypeB可观察从选定的TypeA收集。有意义吗?



绑定DOES工作,它更新。问题是当组合框中的项目呈现者已经显示项目并且用户在dat1中选择不同的TypeA并且试图查看组合框中的新项目时,存在长暂停,而项目呈现者生成新项目。 / p>

要测试这个问题,我可以简化方案。



重现步骤:


  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 =MainWindowHeight =350Width =525>
< Grid>
< StackPanel>
< ComboBox x:Name =cboDisplayMemberPath =Junk1>< / ComboBox>
< Button Content =点击我! 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;组; }
}

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



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



它延迟足够,我认为它可能是由绑定异常引起的,慢慢来。有没有办法看看是否有绑定异常被抛出?

解决方案

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



在上面的例子中,如果我使它例如50或更多的项目,冻结变得非常明显。
重新绑定后,它将挂起约15秒钟,之后我才能再次与其进行交互。



另一个有趣的事情是,在VS.调试。



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



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 =MainWindowHeight = 350Width =525>
< StackPanel>
< ComboBox x:Name =cboDisplayMemberPath =Junk1>< / ComboBox>
< Button Content =点击我! Click =btn_Click>< / Button>
< / StackPanel>
< / Window>

代码

  using System.Collections.ObjectModel; 
使用System.Windows;

命名空间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-+一世 });
}


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

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;组; }
public string Junk2 {get;组; }
}
}

或解决方法。


I have a datagrid (call it dat1) that has an items source bound to an observable collection of a custom type, call it TypeA. One of the properties on TypeA is an observable collection of another custom type, call it TypeB. I then have a combobox with an items source bound to dat1's SelectedItem.TypeB.

So when the user selects a TypeA in dat1, the combobox shows the items in the TypeB observable collection from the selected TypeA. Make sense?

The binding DOES work and it DOES update. The problem is that when the items presenter in the combobox has already displayed items and the user selects a different TypeA in dat1 and tries to view the new items in the combobox, there is a long pause while the items presenter generates the new items.

To test the problem, I can simplify the scenario.

Steps to reproduce:

  1. Create a new WPF project using .NET 4.0.

  2. Cut and Paste the code below.

  3. To get the freezing behavior, you must drop the combobox to see the items, then click the button so the items source changes, and then drop the combobox again. The combobox drops after a few seconds, but why so slow?

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: This is a WPF problem. I've heard Silverlight doesn't have the same issue. I don't need to know if Silverlight works. I need a WPF answer.

PS. The delay is longer when the items source is changed to junk2, presumably because it is larger.

It delays enough that I think it may be caused by binding exceptions, since exceptions take time. Is there a way to see if there are binding exceptions being thrown?

解决方案

I observe this phenomenon too. I'm using Visual Studio 2010 (with ReSharper 6.0) on Windows 7 x64.

It's not noticeable with only four items as in the example above, but if I make it e.g. 50 or more items the freeze gets very noticeable. After the rebinding it will then hang for about 15 seconds before I'm allowed to interact with it again.

Another interesting thing is that this only happens while debugging in VS. If I run the exe standalone it is really snappy and fast.

Here is the code from my simple project:

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

I will post here again if I find a solution or workaround to this.

这篇关于什么是导致我的WPF组合框项目花费这么长时间刷新,当项目资源更改?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆