2012-02-27 71 views
1

我想直觀地顯示一個項目(在我的情況下是一個BitmapImage)已被添加到使用WPF/MVVM的ListBox中的集合。爲了給出一些背景知識,我使用捕捉卡捕捉流式視頻,並且在視頻流式傳輸時拍攝靜態圖像。這些圖像是通過單擊UI上的「靜止圖像」按鈕捕獲的。捕捉圖像後,我想要在UI上的單獨面板中顯示所述圖像的縮略圖。我明白需要做些什麼才能做到這一點,但我似乎無法使其發揮作用。現在,我的模型執行所有數據檢索。更新到ListBox綁定集合後刷新UI

public ObservableCollection<BitmapImage> GetAssetThumbnails() 
{ 
    var imageDir = ImgPath != null ? new DirectoryInfo(ImgPath) : null; 
    if(imageDir != null) 
    { 
     try 
     { 
      foreach (FileInfo imageFile in imageDir.GetFiles("*.jpg")) 
      { 
       var uri = new Uri(imageFile.FullName); 
       _assetThumbnails.Add(new BitmapImage(uri)); 
      } 

     } 
     catch (Exception) 
     { 
      return null; 
     } 
    } 

    return _assetThumbnails; 
} 

我的視圖模型建立在其構造模型的新實例,然後設置公共財產等於_assetModel.GetAssetThumbnails()。 ViewModel具有所有標準的OnPropertyChanged事件和事件處理。

private void OnPropertyChanged(string propertyName) 
{ 
    if(PropertyChanged != null) 
    { 
     PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

#region Public Properties 
public ObservableCollection<BitmapImage> AssetCollection 
{ 
    get { return _assetCollection; } 
    set 
    { 
     if (_assetCollection != value) 
     { 
      _assetCollection = value; 
      OnPropertyChanged("AssetCollection");  
     } 
    } 
} 
#endregion 

private void _assetCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
{ 
    OnPropertyChanged("AssetCollection"); 
} 
public event PropertyChangedEventHandler PropertyChanged; 

然後,在我的XAML文件中,我將ListBox的項目源綁定到AssetCollection。

<ListBox x:Name="lstBoxAssets" ItemsSource="{Binding AssetCollection}" Grid.Row="1" Background="{DynamicResource GrayColor}" Margin="5,0,0,5" ></ListBox> 

我讀過,集合中的每個項目都應該實現INotifyPropertyChanged接口。我試圖創建一個實現該位圖圖像的包裝類,但它也沒有工作。有什麼我在這裏失蹤?圖像最初顯示,但在圖像被捕獲和保存後不刷新。我有一種感覺,這是來自事件PropertyChanged沒有得到調用。我通過調試發現它在檢查時始終爲空,因此從不調用OnPropetyChanged方法。我不知道我應該在哪裏添加這個事件處理程序。我只使用代碼隱藏文件將視圖模型的數據上下文添加到視圖,就是這樣。這正是我通常想要添加任何事件處理的地方。任何人都可以看到簡單的東西,我在這裏失蹤?

+0

嘗試「我試圖創建一個包裝類的位圖圖像實現,但它也沒有工作。」再次。對項目的更改需要通過NotifyPropertyChanged從項目中獲得。你有沒有使用公共財產? – Paparazzi

+0

是的,該物業是公共的。我會嘗試再次創建一個包裝類。我上次可能錯過了一些東西。 – Zajn

回答

2

當您更新列表或更改存儲在集合中的項目時,是否更改ObservableCollection

如果您要更改集合中的項目,您需要找到一種方法告訴WPF,當單個項目發生更改時集合已更改,以便知道重繪它。

通常情況下,集合中的項目實施INotifyPropertyChanged,所以很容易爲PropertyChange通知連接到物品,告訴WPF提高CollectionChanged事件每當屬性更改列表。

// Wireup CollectionChanged in Constructor 
public MyViewModel() 
{ 
    ListOfSomeItems = new List<SomeItem>(); 
    AssetCollection.CollectionChanged += AssetCollection_CollectionChanged; 
} 

// In CollectionChanged event, wire up PropertyChanged event on items 
void AssetCollection_CollectionChanged(object sender, CollectionChangedEventArgs e) 
{ 
    if (e.NewItems != null) 
    { 
     foreach(Asset item in e.NewItems) 
      item.PropertyChanged += Asset_PropertyChanged; 
    } 
    if (e.OldItems != null) 
    { 
     foreach(Asset item in e.OldItems) 
      item.PropertyChanged -= Asset_PropertyChanged; 
    } 
} 

// In PropertyChanged, raise CollectionChanged event 
void Asset_PropertyChanged(object sender, PropertyChangedEventArgs e) 
{ 
    OnPropertyChanged("AssetCollection"); 
} 

如果項目沒有實現INotifyPropertyChanged,你必須手動提升CollectionChanged事件隨時隨地的項目在收集變化。

AssetCollection[0].Thumbnail = new BitmapImage(uri); 
OnPropertyChanged("AssetCollection"); 

如果您是通過添加/刪除項目更改ObservableCollection本身並沒有看到UI更新,那麼它聽起來像它可能是一個語法錯誤的地方,我們看不到。

我看到的最常見的是對私有財產進行更改,而不是公共財產。

// Will not raise the CollectionChanged notification 
_assetCollection = _assetModel.GetAssetThumbnails(); 

// Will raise the CollectionChanged notification 
AssetCollection = _assetModel.GetAssetThumbnails(); 

雖然我也看到很多人誰使用List或自定義集合,而不是ObservableCollection爲好,這不會引發CollectionChanged事件。

+0

那麼,當我捕獲一個新的圖像時,它只保存在ObservableCollection中的圖像保存在同一個目錄中。所以我認爲我需要更改集合中的項目,而不是集合本身。你的例子非常有幫助,謝謝!我會盡量對你列出的一些變化進行檢查,看看它們是否有效。 – Zajn

+0

我打算接受這個答案,因爲這有助於我理解我在代碼中做錯了什麼。我仍然無法正確地更新用戶界面,但這超出了這個問題的範圍,因爲它與創建縮略圖後未引發的事件有關。 – Zajn