Что заставляет мои элементы списков WPF так долго обновляться при изменении источника элементов? - PullRequest
0 голосов
/ 10 декабря 2010

У меня есть сетка данных (назовите ее dat1), источник источника которой связан с наблюдаемой коллекцией пользовательского типа, назовите ее TypeA.Одним из свойств в TypeA является наблюдаемая коллекция другого пользовательского типа, называемого его TypeB.Затем у меня есть комбинированный список с источником элементов, привязанным к SelectedItem.TypeB dat1.

Так что, когда пользователь выбирает TypeA в dat1, комбинированный список показывает элементы в наблюдаемой коллекции TypeB из выбранного TypeA.Имеет смысл?

Привязка работает, и она обновляется.Проблема заключается в том, что, когда презентатор элементов в выпадающем списке уже отображал элементы, а пользователь выбирает другой тип A в dat1 и пытается просмотреть новые элементы в выпадающем списке, происходит долгая пауза, пока презентатор элементов создает новые элементы.

Чтобы проверить проблему, я могу упростить сценарий.

Шаги для воспроизведения:

  1. Создание нового проекта WPF с использованием .NET 4.0.

  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, предположительно потому, что он больше.

Это задерживает достаточно, так что я думаю, что это может быть вызвано привязкой исключений, так как исключения занимают время.Есть ли способ увидеть, если выбрасываются исключения привязки?

1 Ответ

0 голосов
/ 22 сентября 2011

Я тоже наблюдаю это явление. Я использую Visual Studio 2010 (с ReSharper 6.0) на Windows 7 x64.

Это не заметно только с четырьмя предметами, как в примере выше, но если я сделаю это, например. При 50 и более предметах заморозка становится очень заметной. После повторного связывания он будет зависать примерно 15 секунд, прежде чем мне снова разрешат с ним взаимодействовать.

Другая интересная вещь заключается в том, что это происходит только при отладке в VS. Если я запускаю exe-файл автономно, он действительно быстрый и быстрый.

Вот код из моего простого проекта:

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

Я опубликую здесь снова, если найду решение или обходной путь к этому.

...