Эквивалент BeginUpdate в WPF? - PullRequest
9 голосов
/ 05 мая 2010

Моя проблема в том, что мне нужно добавить много элементов в ListBox в WPF. В WinForms вы просто используете метод BeginUpdate (); , добавляете все и, наконец, используете метод EndUpdate (); .

Итак, как мне остановить рисование в списке WPF, пока не будет добавлен каждый элемент, а затем нарисовать все за один раз?

Ответы [ 3 ]

12 голосов
/ 05 мая 2010

Правильно используйте Диспетчер.

Вы должны добавить вещи в свой ListBox (или его источник данных) из потока Dispatcher, иначе пользовательский интерфейс взорвется. Когда вы делаете это, вы либо находитесь в методе в этом потоке, либо (возможно, более вероятно) в фоновом потоке и используете Dispatcher.BeginInvoke для добавления элемента.

Когда вы отправляете обновление Диспетчеру, используйте Dispatcherpriority.Normal в качестве приоритета. Диспетчер имеет очередь рабочих элементов, и ваши Normal элементы будут выдвигаться (возможно, на удивление) высоко в этой очереди.

Бит кода, который WPF запускает для обновления привязки данных, когда базовые данные были изменены, работает в DispatcherPriority.DataBind, что ниже Normal. Это означает, что привязка данных, как правило, не будет обновляться до тех пор, пока не будут добавлены все ваши элементы (или, альтернативно, если добавление ваших элементов занимает много времени, это может произойти, когда диспетчер бездействует между добавлением элементов).

Бит кода, который фактически отображает ваш элемент управления (скажем, когда его привязка сигнализирует об обновлении), работает на DispatcherPriority.Render и имеет даже более низкий приоритет, чем привязка. Это означает, что ваш элемент управления будет отображаться только тогда, когда в Dispatcher закончились привязки для обновления, что, в свою очередь, произойдет только тогда, когда в Dispatcher закончится добавление элементов в процесс.

Если это звучит странно, помните, что каждый слой (update - binding - render) вызывает метафорический флаг для слоя ниже - вы не получаете десять привязок, а затем происходит десять визуализаций. Если вы быстро добавите свой предмет, вы получите все ваши добавления, за которыми следует одно связывание и одно рендеринг - что идеально.

По сути: если вы используете Диспетчер как он задумывался, вам не о чем беспокоиться. Кажется «неправильным» иметь рендеринг как относительно низкий приоритет для Dispatcher, но на самом деле это очень умно: -)

5 голосов
/ 05 мая 2010

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

Если вы добавите фрагменты своего XAML и код к вопросу (чтобы показать нам, что вы в данный момент делаете), мы могли бы предоставить лучший ответ.

РЕДАКТИРОВАТЬ: Добавлен очень простой пример.

Вот пример, который связывает модель представления с главным окном (представлением), а затем XAML объявляет, что данные ListBox связаны с свойством Numbers модели представления.

MainViewModel.cs

public class MainViewModel
{
    public IEnumerable<int> Numbers
    {
        get { return Enumerable.Range(1, 1000); }
    }
}

MainWindow.xaml

<Window
  x:Class="WpfApplication1.MainWindow"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Height="350"
  Width="525"
  >
  <ListBox ItemsSource="{Binding Numbers}"/>
</Window>

MainWindow.xaml.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new MainViewModel();
    }
}

Если вы только начинаете работать с WPF, я могу очень рекомендовать Windows Presentation Foundation Unleashed от Адама Натана. Это отличная книга, и она в цвете для загрузки. Чтение других книг после этого похоже на возврат в Блокнот после использования Visual Studio.

Подробнее об этой модели Model-View-ViewModel можно узнать из книги Джоша Смита Advanced MVVM .

3 голосов
/ 05 мая 2010

Видя, что вы работаете с большими списками, вы, возможно, захотите взглянуть на виртуализацию пользовательского интерфейса WPF. Вот хорошая серия постов блогов об этом:

http://blogs.msdn.com/dancre/archive/tags/VirtualizingTilePanel/default.aspx

Обычно вы бы помещали элементы в коллекцию и привязывали данные этой коллекции к элементу управления списка. Список, если все сделано правильно, не должен обновлять элементы, которые добавляются и не видны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...