2012-08-06 7 views
0

Я пытаюсь связать некоторое BindingList с ComboBox элементом управления в моем приложении WPF. Но, Мой BindingList обновлен из другой темы, кроме потока пользовательского интерфейса.Обновление BindingLIst, связанное с ComboBox, из потока, отличного от потока пользовательского интерфейса

Я составил модель. Все, что вам нужно, это новый пустой проект со ссылками на WindowsBase, PresentationCore, PresentationFramework, System.Xaml (или просто перетащите его в предопределенное окно WPF).

using System; 
using System.ComponentModel; 
using System.Threading; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 

public class MainWindow : Window 
{ 
    [STAThread] 
    public static void Main() 
    { 
     new MainWindow().ShowDialog(); 
    } 

    public MainWindow() 
    { 
     BindingList<string> list = new BindingList<string>(); 
     ComboBox cb = new ComboBox(); 
     cb.SetBinding(ComboBox.ItemsSourceProperty, new Binding() { Source = list }); 
     this.Content = cb; 
     list.Add("Goop"); 
     new Thread(() => 
     { 
      list.Add("Zoop"); 
     }).Start(); 
    } 
} 

В линии Goop все в порядке. Но, когда он дойдет до Zoop линии, это thorws исключения:

Этого типа CollectionView не поддерживает изменения в его SourceCollection из нити, отличающихся от Dispatcher потока.

В реальном проекте я не могу переместить list.Add в поток пользовательского интерфейса, и я хочу сохранить проблему Binding. Как это можно решить? Я могу перейти в другой «список», чем BindingList. Я пробовал простой List<string>, но это хуже: он не обновляется вообще, когда я добавляю новые элементы.

EDIT

В действительности, добавление-нить знает список, но он не знает, окно WPF. Список находится в классе с внутренней работой, а GUI проверяет класс и просматривает его. Итак, Add не должен знать о графическом интерфейсе.

ответ

0

Попробуйте это,

new Thread(() => 
    { 
     if (cb.Dispatcher.CheckAccess()) 
     { 
      list.Add("Zoop"); 
     } 
     else 
     { 
     cb.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, 
       new Action(delegate 
         { 
          list.Add("Zoop"); 
         } 
     )); 
     } 
    }).Start(); 

надеюсь, что это помогает

+0

Спасибо. Я обновил вопрос. В реальности добавочный поток знает список, но он не знает окно WPF. Список находится в классе с внутренней работой, а GUI проверяет класс и просматривает его. Таким образом, 'Add' не должен знать о GUI. –

+0

Вы должны использовать шаблон дизайна, такой как MVVM http://mvvmlight.codeplex.com/. Это легко понять и избегать вашей проблемы. – David

0

UI-нить - замок. Затем вы должны предоставить ему свои данные в специальной функции. MSDN BeginInvoke

с помощью:

BeginInvok(()=>{ // Your stuff}); 

Спросишь пользовательский интерфейс, чтобы обновить ваш взгляд, как только это возможно для него.

+0

Спасибо. Я обновил вопрос. В реальности добавочный поток знает список, но он не знает окно WPF. Список находится в классе с внутренней работой, а GUI проверяет класс и просматривает его. Таким образом, 'Add' не должен знать о GUI. –