Joseph Katzman
Joseph Katzman

Reputation: 2085

How refresh items on a content page?

I read a lot of topics about usage of ObservableCollection, but I don't understand what should I do in my case. I have the following PageContent structure:

enter image description here

I use IList collection to store my Xamarin.Form.Image. I take it from the database. The number of the grid layout rows and columns definitely depend on the number of images in a database. User can load new images to a database. It ads to a database by using ImageRepository and it ads to the IList<T> collection, but I don't know how to dynamically redraw my grid layout. I tried to do this as follows:

//this.images 
//is a IList<Images> which stores as property of the class.

        private void OnClickSearchImagesButton(object sender, EventArgs args)
        {
            IFiler filer = DependencyService.Get<IFiler>();
            // Get all paths of the images
            IEnumerable<string> filesPath = filer.GetFilesPaths(FileExtension.JPG);
            IEnumerable<Image> images = filesPath.Select(f => new Image { Source = ImageSource.FromFile(f) });

            foreach (Image img in images)
            {
                // If found image does not exist
                // Add it to a database
                // --------------------

                // Redraw grid layout
                this.gridLayout = new Grid();

                const int numberOfImagesPerRow = 3;
                int numberOfImages = this.images.Count;
                int numberOfRows = (int)Math.Ceiling((double)numberOfImages / numberOfImagesPerRow);

                // configure grid layout
                for (int i = 0; i < numberOfRows; i++)
                {
                    this.gridLayout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(200) });
                }

                for (int i = 0; i < numberOfImagesPerRow; i++)
                {
                    this.gridLayout.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
                }

                for (int i = 0, imageNumber = 0; i < numberOfRows; i++)
                {
                    for (int j = 0; j < numberOfImagesPerRow && imageNumber < numberOfImages; j++, imageNumber++)
                    {
                        this.gridLayout.Children.Add(images[imageNumber], j, i);
                    }
                }
            }
        }

But it didn't help me. I saw some topics when people use ObservableCollection for items instead of List. I'm a little bit confused with it, because I think that I need to store all my items in ObservableCollection. Please, could you explain me what is the best way to hold actual information on the page?

Upvotes: 3

Views: 976

Answers (2)

Ben Reierson
Ben Reierson

Reputation: 1099

ObservableCollection is helpful because it fires events when the collection changes, but you need to either use a control that consumes those events, or create one yourself. In your case, I would suggest looking at some third party controls that layout images as you want (another answer mentioned FlowListView), or look at creating a custom layout in Xamarin Forms.

Upvotes: 1

Alessandro Caliaro
Alessandro Caliaro

Reputation: 5768

ObservableCollection is very useful when you use controls like ListView. If you add a record or remove a record from the ObservableCollection, ListView updates automatically.

If you create a Grid and add Images to it, you should add or remove items "by code". ObservableCollection can't help you.

If you need a ListView that display images (so you can use ObservableCollection) you can take a look to

FlowListView

it's a powerful plugin that can visualize Images in a List

DataTemplate and DataTemplateSelector support

Fixed or automatic column count

Grouping support

Columns can expand to empty space (configurable)

ANY View can be used as a cell

All Xamarin.Forms platforms supported

Simple sample

<flv:FlowListView FlowColumnCount="3" SeparatorVisibility="None" HasUnevenRows="false"
    FlowItemTappedCommand="{Binding ItemTappedCommand}" FlowLastTappedItem="{Binding LastTappedItem}"
    FlowItemsSource="{Binding Items}" >

    <flv:FlowListView.FlowColumnTemplate>
        <DataTemplate>
            <Label HorizontalOptions="Fill" VerticalOptions="Fill" 
                XAlign="Center" YAlign="Center" Text="{Binding Title}"/>
        </DataTemplate>
    </flv:FlowListView.FlowColumnTemplate>

</flv:FlowListView>

If you need a demo

DEMO

Upvotes: 3

Related Questions