Answered by:
Data binding with ObservableCollection and CollectionViewSource

Question
-
Hi,
I've been fighting with this for a while now and cannot seem to get it to work.
I have the following code in XAML:
<CollectionViewSource x:Name="uploadsCVS" x:Key="uploadsCVS"/> <GridView x:Name="ItemGridView" Width="Auto" Height="250" Background="{StaticResource PageBackgroundBrush}" ItemsSource="{Binding Source={StaticResource uploadsCVS}}" ItemContainerStyle="{StaticResource StoreFrontTileStyle}" ItemsPanel="{StaticResource StoreFrontGridItemsPanelTemplate}" BorderBrush="LightGray" BorderThickness="1" VerticalAlignment="Stretch" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto" SelectionMode="Single" SelectionChanged="ItemGridView_SelectionChanged"> <GridView.ItemTemplate> <DataTemplate> <Grid HorizontalAlignment="Left" Background="White"> <StackPanel Orientation="Horizontal" Margin="10,10,0,0"> <Image Source="{Binding Image}" Height="60" Width="60" VerticalAlignment="Center" Margin="0,0,10,0"/> <StackPanel Margin="0,0,0,0" Orientation="Vertical"> <TextBlock TextWrapping="Wrap" Style="{StaticResource ItemTitleStyle}" Width="200" VerticalAlignment="Center" Text="{Binding Title}" HorizontalAlignment="Left" FontFamily="Segoe UI" /> <TextBlock TextWrapping="Wrap" Style="{StaticResource ItemSubtitleStyle}" Width="200" MaxHeight="20" VerticalAlignment="Center" Text="{Binding Description}" HorizontalAlignment="Left"/> </StackPanel> </StackPanel> </Grid> </DataTemplate> </GridView.ItemTemplate> </GridView>
And then I have this in the code behind:public ObservableCollection<Upload> uploads = new ObservableCollection<Upload>(); public MainPage() { InitializeComponent(); uploadsCVS.Source = uploads; } async private void Add_Tapped(object sender, Windows.UI.Xaml.Input.TappedEventArgs e) { var picker = new Windows.Storage.Pickers.FileOpenPicker(); picker.FileTypeFilter.Add(".png"); picker.FileTypeFilter.Add(".jpg"); var files = await picker.PickMultipleFilesAsync(); foreach (var f in files) { var image = new BitmapImage(); image.SetSource(await f.OpenAsync(Windows.Storage.FileAccessMode.Read)); Upload u = new Upload(); u.Image = image; uploads.Add(u); } }
(Upload is a regular class with a few properties such as Title, Description, Image)
During debug "uploads" gets populated properly, even ItemGridView.Items is updated whenever an Upload object is added to the observable collection. The only problem is that nothing gets displayed in the GridView...Any help will be greatly appreciated.
Ana
Monday, September 19, 2011 2:24 PM
Answers
-
See this thread for more details. ObservableCollection is not working correctly in Build bits. Instead you have to use the ObservableVector<T> type from this sample. Also note that for Build, you have to use ObservableVector<object>.
Joe
- Marked as answer by Matt SmallMicrosoft employee, Moderator Monday, September 19, 2011 5:24 PM
Monday, September 19, 2011 4:42 PM
All replies
-
Hi Ana,
I'm trying to reproduce your problem but the code shown here does not compile due to missing references - what are they in your application?
Matt Small - Microsoft Escalation Engineer - Forum ModeratorMonday, September 19, 2011 3:15 PMModerator -
Hi Matt,
Here are my usings for the code behind page:
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using Windows.Foundation; using Windows.Graphics.Display; using Windows.UI.ViewManagement; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls.Primitives; using Windows.UI.Xaml.Data; using Windows.UI.Xaml.Media.Imaging;
I am also including Upload.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Windows.UI.Xaml.Data; using Windows.UI.Xaml.Media; namespace MyApp { public class Upload { private string _title = "No title"; public string Title { get { return this._title; } set { if (this._title != value) { this._title = value; } } } private string _tags = string.Empty; public string Tags { get { return this._tags; } set { if (this._tags != value) { this._tags = value; } } } private string _description = string.Empty; public string Description { get { return this._description; } set { if (this._description != value) { this._description = value; } } } } }
I hope this gives you enough information and thanks for looking into it.Ana
- Edited by anacrisan Monday, September 19, 2011 4:32 PM
- Proposed as answer by Joe Stegman [MSFT]Microsoft employee Monday, September 19, 2011 4:40 PM
Monday, September 19, 2011 4:31 PM -
I have found when using awaits (not sure if just in UI thread) exceptions seem to just get swallowed. Try wrapping your code in manual try catches to see if any exceptions are being thrown.
- Edited by erothvt Monday, September 19, 2011 4:42 PM
Monday, September 19, 2011 4:41 PM -
See this thread for more details. ObservableCollection is not working correctly in Build bits. Instead you have to use the ObservableVector<T> type from this sample. Also note that for Build, you have to use ObservableVector<object>.
Joe
- Marked as answer by Matt SmallMicrosoft employee, Moderator Monday, September 19, 2011 5:24 PM
Monday, September 19, 2011 4:42 PM -
Thanks Joe. That did the trick - should teach me to look at the samples more closely :)Monday, September 19, 2011 5:35 PM
-
ObservableVector worked like a charm for me as well. I tried for hours last weekend trying to get my ListView to refresh and thought I was doing the DataBinding wrong :)
I hope this is fixed in the Beta build as I imagine it will cause headaches for a lot of other developers.
Thursday, September 22, 2011 4:19 AM -
See this thread for more details. ObservableCollection is not working correctly in Build bits. Instead you have to use the ObservableVector<T> type from this sample. Also note that for Build, you have to use ObservableVector<object>.
Joe
Thursday, September 22, 2011 6:01 PM -
Is adding to the ObservableVector thread/task save? I am filling the vector in a background task (from file) - and during that I am receiving a strange exception.
In VectorChanged:
An exception of type 'System.InvalidCastException' occurred in myhealth.exe but was not handled in user code
Additional information: Unable to cast COM object of type 'Windows.Foundation.Collections.VectorChangedEventHandler`1[System.Object]' to class type 'Windows.Foundation.Collections.VectorChangedEventHandler`1[System.Object]'. Instances of types that represent COM components cannot be cast to types that do not represent COM components; however they can be cast to interfaces as long as the underlying COM component supports QueryInterface calls for the IID of the interface.
Sunday, September 25, 2011 1:58 PM -
Tamlocar,
You have to add items to your ObservableVector from your VM by the same way:
CurrentDispatcher.Invoke(CoreDispatcherPriority.Normal, (s, e) => ObservableVectorInstance.Add(e.Context), this, smeObject);
Dont forget to initialize CurrentDispatcher with the proper dispatcher object instance.- Edited by HeToC Sunday, November 6, 2011 5:33 PM
Sunday, November 6, 2011 5:32 PM