2011-12-14 65 views
1

我有一個WPF應用程序正在數據庫中查找新圖像,如果出現問題,它會將圖像添加到列表中。當這個事件發生時,我希望它將圖像添加到StackPanel中。將圖像添加到WPF中的StackPanel中

首先,我試圖插入圖像,但得到了一個InvalidOperationException說:「調用線程必須是STA,因爲許多UI組件需要這個。」並提出了:

public void Instance_GraphicChanged(object sender, PropertyChangedEventArgs e) 
{ 
    foreach (Model.Graphic item in Model.IncomingCall.Instance.Graphics) 
    { 
     if(!_strings.Contains(item.ImageId.ToString())) 
     { 
      Thread thread = new Thread(new ThreadStart(
       delegate() 
       { 
        //sp_images StackPanel for Images 
        sp_images.Dispatcher.Invoke(
         DispatcherPriority.Normal, new Action(
          delegate() 
          { 
           Image img = new Image(); 
           img.Source = item.ImageObj; //ImageObj returns a BitmapImage 
           sp_images.Children.Add(img); 
          } 
        )); 
       } 
      )); 
      _strings.Add(item.ImageId.ToString()); 
     } 
    } 
} 

這不拋出任何類型的異常,但實際上什麼也沒有發生......

+0

你不需要創建一個新的線程來調用'Dispatcher'。相反,您應該使用委託調用'sp_images.Dispatcher.BeginInvoke(...)'。另外,你有沒有嘗試將圖像生成綁定到'ItemsControl'?您可以使用模板將其轉換爲'StackPanel',並且只使用包含在「ObservableCollection」中的'BitmapImage'對象。 –

回答

2

在參考我的意見,你可以嘗試這樣的事:

XAML

<!-- ... Other XAML Code ... --> 
<ItemsControl x:Name="sp_images"> 
    <ItemsControl.ItemsPanel> 
     <StackPanel Orientation="Horizontal" /> 
    </ItemsControl.ItemsPanel> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
      <Image Source="{Binding}" /> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl> 

代碼隱藏

private readonly HashSet<string> mImageIds = new HashSet<string>(); 
private readonly ObservableCollection<BitmapImage> mImages = new ObservableCollection<BitmapImage>(); 

// ... Inside the constructor 
{ 
    InitializeComponent(); 

    sp_images.ItemsSource = mImages; 
} 

public void Instance_GraphicChanged(object sender, PropertyChangedEventArgs e) 
{ 
    foreach (Model.Graphic item in Model.IncomingCall.Instance.Graphics) 
    { 
     // Have we already seen the image 
     if (mImageIds.Add(item.ImageId.ToString())) 
     { 
      // We've not seen the image yet, so add it to the collection 
      // Note: We must invoke this on the Dispatcher thread. 
      this.Dispatcher.BeginInvoke((Action)delegate() 
      { 
       mImages.Add(item.ImageObj); 
      }); 
     } 
    } 
} 

這應該繞過您以前可能遇到的任何跨線程異常。它還應該允許您輕鬆地將新圖像添加到ObservableCollection,該圖像將自動使用圖像更新UI。此外,使用ItemTemplate意味着您不必每次都實際構建UI; WPF會爲你處理。

有關使用ObservableCollection的更多信息,請參閱here。另請參閱此StackOverflow question以獲取有關容器模板的說明。

+0

非常感謝您的輸入,它看起來像是通向最終解決方案的一大步,但我得到一個NotSupportedException,將imageObj添加到mImages集合中。 詳情說:「這種類型的CollectionView不支持從與分派器線程不同的線程更改其SourceCollection。」 – Morten

+0

啊,是的,它的確如此。我編輯了我的答案來解決這個問題。 –

+0

並再次感謝您... 我現在得到Markup.XAMLParseException,並且詳細信息是:必須在與DependencyObject相同的線程上創建DependencySource。 然後,我試圖凍結BitmapImage添加它之前,它告訴我,我無法訪問它,因爲它是從另一個線程... 再次,感謝您的幫助... – Morten