locked
Data binding with ObservableCollection and CollectionViewSource RRS feed

  • 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

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 Moderator
    Monday, September 19, 2011 3:15 PM
    Moderator
  • 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

     

     


    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

    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

    Thanks for the clarification Joe - solved my issues. From what you wrote, is it safe to conclude that at some point ObservableCollection<T> will work again, or is ObservableVector<object> the new solution required by the interactions with JavaScript etcetera?
    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