2013-01-04 3 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 변경된 그것의 품목. 내가 가진 MainThread에 ComboBox (CourseList)를 업데이트 할 때 는 : 변경 CourseList

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); 
      } 
    } 

모든 요소하지만 ComboxBox 아무 일도 발생하지 않습니다에 (내가 Textbox에서 볼 수 있습니다.)

아이디어가 있으십니까?

+0

그냥 배제하기 위해, 콤보 상자 XAML에서 CourseSelectedItem 및 CourseSelectedIndex을 바인딩 해제 시도 그리고 무슨 일이 일어나는 지보십시오. 두 속성을 모두 설정하면 상황이 이상해 질 수 있습니다. – TMan

답변

1

시도 ObervableCollection<T>

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

결합 단 (목록이 할당 될 때) CourseList 설정되는 UI가 통지되지 그 내용이 변경 될 때 변경 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은 Dispatcher Thread에서만 변경할 수 있으므로 호출해야합니다. 맞습니까? – derWilly

+0

예, "다른"스레드에서 직접 호출하는 대신 Add 및 Clear 메서드 호출을 호출하십시오. –

+0

Romoku와 Jason에게 감사드립니다! – derWilly

관련 문제