2013-01-04 35 views
0

我有一個列表的問題,它綁定到一個ComboBox列表<string>綁定到組合框

List:在ComboBox

private List<string> _CourseList = new List<string>(); 
public List<string> CourseList 
     { 
      get { return _CourseList; } 
      set 
      { 
       _CourseList = value; 
       OnPropertyChanged("CourseList"); 
      } 
     } 

XAML代碼:

<ComboBox x:Name="cbxCourse" Height="23" MinWidth="100" Margin="5,1,5,1" VerticalAlignment="Top" ItemsSource="{Binding Path=CourseList}" IsEnabled="{Binding Path=CanExport}" SelectedIndex="{Binding Path=CourseListSelectedIndex}" SelectedItem="{Binding Path=CourseListSelectedItem}" SelectionChanged="cbxCourse_SelectionChanged"/> 

現在我填的是List從另一個線程:

void Database_LoadCompleted(object sender, SqliteLoadCompletedEventArgs e) 
{ 
    foreach (DataTable Table in DataSetDict[CampagneList[0]].Tables) 
    { 
     CourseList.Add(Table.TableName); 
    } 
} 

一切看起來不錯,而且ComboBox變其項目。 當我嘗試更新ComboBoxCourseList)在MainThread:

private void cbxCampagne_SelectionChanged(object sender, EventArgs e) 
    { 
     if (cbxCampagne.SelectedItem != null) 
     { 
      CourseList.Clear(); 
      foreach (DataTable Table in DataSetDict[CampagneList[_CampagneListSelectedIndex]].Tables) 
      { 
       CourseList.Add(Table.TableName); 
      } 
    } 

CourseList改變了一切元素(我可以看到它在Textbox),但在ComboxBox什麼也沒有發生。

任何想法?

+0

剛剛排除,嘗試從ComboBox XAML解除綁定您的CourseSelectedItem和CourseSelectedIndex並看看會發生什麼。有時在設置這兩個屬性時,事情會變得很奇怪。 – TMan

回答

1

嘗試改變CourseListObervableCollection<T>

http://msdn.microsoft.com/en-us/library/ms668604.aspx

綁定只有當通知是CourseList設定(分配列表時)用戶界面,而不是當它的內容發生變化。

一些代碼從Invoke event on MainThread from worker thread

這表明List<>不會改變一次分配和ObservableList<>將發生變化。

視圖模型

//Viewmodel 
public class WindowViewModel : INotifyPropertyChanged 
{ 
    private volatile bool _canWork; 
    private List<string> _items; 
    private ObservableCollection<string> _obervableItems; 

    public WindowViewModel() 
    { 
     //Queue some tasks for adding and modifying the list 
     ThreadPool.QueueUserWorkItem(AddItems); 
     ThreadPool.QueueUserWorkItem(ModifyItems); 

     //Create a background worker to do some work and then we can bind the output to 
     //our ObservableList 
     var obervableWorker = new BackgroundWorker(); 
     obervableWorker.DoWork += ObervableWorkerOnDoWork; 
     obervableWorker.RunWorkerCompleted += ObervableWorkerOnRunWorkerCompleted; 

     obervableWorker.RunWorkerAsync(); 
    } 

    private void ObervableWorkerOnRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs runWorkerCompletedEventArgs) 
    { 
     var items = ObservableItems as ObservableCollection<string>; 

     var workerItems = runWorkerCompletedEventArgs.Result as List<string>; 

     foreach (var workerItem in workerItems) 
     { 
      items.Add(workerItem); 
     } 

     for (int i = 50; i < 60; i++) 
     { 
      var item = items.First(x => x == i.ToString()); 
      items.Remove(item); 
     } 
    } 

    private void ObervableWorkerOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs) 
    { 
     Thread.Sleep(100); 
     int count = 0; 
     var items = new List<string>(); 
     while (100 > count++) 
     { 
      items.Add(count.ToString()); 
     } 

     doWorkEventArgs.Result = items; 
    } 

    private void ModifyItems(object state) 
    { 
     while (!_canWork) 
     { 
      Thread.Sleep(100); 
     } 
     var items = Items as List<string>; 
     for (int i = 50; i < 60; i++) 
     { 
      items.RemoveAt(i); 
     } 
    } 

    private void AddItems(object state) 
    { 
     Thread.Sleep(100); 
     int count = 0; 
     var items = Items as List<string>; 
     while (100 > count++) 
     { 
      items.Add(count.ToString()); 
     } 
     _canWork = true; 
    } 

    public IEnumerable<string> Items 
    { 
     get { return _items ?? (_items = new List<string>()); } 
     set { _items = new List<string>(value); 
      OnPropertyChanged(); 
     } 
    } 

    public IEnumerable<string> ObservableItems 
    { 
     get { return _obervableItems ?? (_obervableItems = new ObservableCollection<string>()); } 
     set { _obervableItems = new ObservableCollection<string>(value); OnPropertyChanged();} 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    [NotifyPropertyChangedInvocator] 
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

窗口

//Window.Xaml 
<Window x:Class="ComboBox.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:comboBox="clr-namespace:ComboBox" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.DataContext><comboBox:WindowViewModel /></Window.DataContext> 
    <Grid> 
     <ComboBox Width="200" Height="22" ItemsSource="{Binding Items}"></ComboBox> 
     <ComboBox Margin="0,44,0,0" Width="200" Height="22" ItemsSource="{Binding ObservableItems}"></ComboBox> 
    </Grid> 
</Window> 

這可以很容易地修改爲使用調度調用:Change WPF controls from a non-main thread using Dispatcher.Invoke

+0

但ObervableCollection只能在調度程序線程中更改,所以我必須調用,對嗎? – derWilly

+0

是的,調用Add和Clear方法調用,而不是直接從「其他」線程調用它們。 –

+0

謝謝你Romoku和傑森! – derWilly