2010-05-04 20 views
8

Mój problem polega na tym, że muszę dodać wiele elementów do ListBox w WPF. W WinForms wystarczy użyć BeginUpdate(); metoda, dodaj wszystko i na końcu użyj EndUpdate(); Metoda.BeginUpdate odpowiednik w WPF?

Jak zatrzymać rysowanie w skrzynce WPF, aż do dodania każdego elementu, a następnie narysować wszystko za jednym razem?

Odpowiedz

5

Wygląda na to, że programowo możesz dodawać elementy do listy pojedynczo. Lepszym rozwiązaniem byłoby przechowywanie elementów, które mają być wyświetlane w modelu, i powiązanie modelu z kontekstem danych pola listy. Pozwoli to na zajęcie się aktualizacjami renderowania przez WPF.

Jeśli dodasz fragmenty kodu XAML i kodu do pytania (aby pokazać nam, co aktualnie robisz), możemy być w stanie zapewnić lepszą odpowiedź.

EDYCJA: Dodano bardzo prosty przykład.

Oto przykład, który wiąże model widoku z głównym oknem (widokiem), a następnie XAML deklaruje, że dane ListBox są powiązane z właściwością modelu widoku modelu 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(); 
    } 
} 

Jeśli dopiero zaczynasz z WPF, mogę wysoce polecam Windows Presentation Foundation Unleashed przez Adama Nathana. To świetna książka i jest w kolorze do uruchomienia. Czytanie innych książek po tym jest jak powrót do Notatnika po użyciu Visual Studio.

Aby uzyskać więcej informacji na temat tego modelu-View-ViewModel, zobacz książkę Josh Smitha Advanced MVVM.

+0

Tak, programowo dodaje elementy do ListBox. Cóż, nie ma zbyt wiele kodu do pokazania, ponieważ nie zakodowałem jeszcze całej aplikacji, po prostu testuję, jak to zrobić, używając Listbox i następującego kodu: dla (int i = 0; i <1000; i ++) { lbQuery.Items.Add (i); } W każdym razie, czy możesz podać przykładowy kod swojego rozwiązania? – Lith

+0

+1, budowanie ich na liście jako pierwsze byłoby znacznie lepsze. O ile nie jest to niemożliwe, będziesz musiał żyć z narzutem przerysowania dla każdego dodatku. –

+1

Jeśli możesz szybko wypełnić całą listę, powinieneś to zrobić przed powiązaniem ... jeśli nie, to nie musisz koniecznie przerysowywać każdego dodania, jeśli możesz dodać partię w czasie lub coś podobnego. –

12

Skorzystaj poprawnie z Dispatchera.

Musisz dodać rzeczy do swojego ListBoxa (lub jego źródła danych) z wątku Dispatchera, inaczej interfejs użytkownika eksploduje. Kiedy to zrobisz, jesteś już w metodzie w tym wątku lub (mam nadzieję, że bardziej prawdopodobne) jesteś w wątku w tle i używasz Dispatcher.BeginInvoke, aby dodać przedmiot.

Po skopiowaniu aktualizacji do programu rozsyłającego należy użyć priorytetu Dispatcherpriority.Normal. Dyspozytor ma kolejkę elementów do pracy, a twoje przedmioty o wartości Normal wpychają się (być może zaskakująco) w tę kolejkę.

Bit kodu uruchamiany przez WPF w celu aktualizacji powiązania danych po zmianie danych bazowych na DispatcherPriority.DataBind, który jest niższy niż Normal. Oznacza to, że powiązanie danych zwykle nie będzie aktualizowane, dopóki wszystkie pozycje nie zostaną dodane (lub, alternatywnie, jeśli dodawanie elementów zajmie dużo czasu, może się zdarzyć, gdy dyspozytor będzie bezczynny między dodawaniem elementów).

Bit kodu, który faktycznie renderuje formant (powiedzmy, gdy jego powiązanie sygnalizuje aktualizację) działa pod numerem DispatcherPriority.Render i ma nawet niższy priorytet niż powiązanie. Oznacza to, że kontrola będzie się wyświetlać tylko wtedy, gdy w Dispatcherze zabraknie powiązań do aktualizacji, co z kolei nastąpi tylko wtedy, gdy w Dispatcherze zabraknie pozycji - dodaje do procesu.

Jeśli brzmi to dziwnie, pamiętaj, że każda warstwa (update - binding - render) powoduje ustawienie metaforycznej flagi na poniższej warstwie - nie uzyskasz dziesięciu powiązań, a następnie stanie się dziesięć renderów. Jeśli Twój przedmiot jest szybki, otrzymasz wszystkie dodane elementy, a następnie jedno bindowanie i jeden rendering - co jest idealne.

Zasadniczo: jeśli użyjesz Dispatchera jako zamierzonego, nie będziesz się martwić. Wydaje się "niesłuszne", aby render był relatywnie niskim priorytetem dla Dispatchera, ale w rzeczywistości jest bardzo sprytny :-)

3

Widząc, że pracujesz z dużymi listami, możesz chcieć rzucić okiem na wirtualizację WPF. Oto dobra seria blogów postów o tym:

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

Normalnie byś elementy do gromadzenia i mają ten zbiór z danymi do kontroli listbox. Listbox, jeśli zostanie wykonany prawidłowo, nie powinien odświeżać elementów, które są dodawane i nie są widoczne.