question

MichaelPleick-3142 avatar image
0 Votes"
MichaelPleick-3142 asked JarvanZhang-MSFT edited

Xamarin loops over the contents of a list view


Hallo,
I have a small app in Xamarin for Andrios and IOS in c#. A list is displayed there via a list view. Itemsource is an ObservableCollection that is used to load data from a local database (SQLite). These data can be filtered by the user using various functions. Everything is working well.
Now I want to loop through and process the data displayed in the ListView. To do this, I need the "ID" field in the list view of every displayed data record. I can't find a solution online. This is also possible in other environments such as VB.NET.

I have tried it this way and that.

ObservableCollection<Classes.jGeraete> result = new ObservableCollection<Classes.jGeraete>();
result = (ObservableCollection<Classes.jGeraete>)myList.ItemsSource;

foreach (var item in result.ToList())
{
DisplayAlert("Meldung", item.ID.ToString(), "ok");
}

Can someone help me?

Thanks Michael

dotnet-xamarin
· 6
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

To do this, I need the "ID" field in the list view of every displayed data record.

Hi, MichaelPleick-3142. Try to detect the ItemAppearing event of the listView, you could get the item index of the item that has been displayed in this event.

public partial class TestPage : ContentPage
{
    TestViewModel viewModel;
    ObservableCollection<TestModel> collection;
    public TestPage()
    {
        InitializeComponent();

        viewModel = new TestViewModel();
        collection = viewModel.DataCollection;
        BindingContext = viewModel;
    }

    private void ListView_ItemAppearing(object sender, ItemVisibilityEventArgs e)
    {
        var number = collection.Count;
        if (e.ItemIndex == number - 1)
        {
            //perform the work
        }
    }
}
0 Votes 0 ·

Hallo and Thanks for your Answer.

do I understand the code correctly? a global collection is defined and this is used later in a loop?

Best Regards,
Michael

0 Votes 0 ·

The collection is from the viewModel class and it is just the one you bind the ItemsSource for the listView.

0 Votes 0 ·

maybe I asked the question wrong (sorry, I'm better in German). in one procedure I set the itemsource of a ListView and in another procedure I want to execute a loop over the contents of the Listview.

I would like to describe this using an example in .NET with a DataGridView. c# is still quite new to me.

sub Procedur1()
Datagridview. Datasource = Data
end Sub

sub myLoop()
dim data as datatable
data=Datagridview.Datasource
for each r in data.rows
....
next
end Sub

or

Sub myLoop2()

for i=0 to Datagridview.Rows.Count-1
....
loop
end sub

is that better explained?

Best Regard,
Michael

0 Votes 0 ·

Do you want to scroll the items in a loop? ListView doesn't provide a property to loop the items. A workaround is to add the items to itemsSource when scrolling to the last item.

What view do you want to display and loop? Xamarin.Forms.CarouselView provides the loop function, you could try it.

https://docs.microsoft.com/en-us/dotnet/api/xamarin.forms.carouselview.loop?view=xamarin-forms

0 Votes 0 ·

I show an OrderList consisting of orders for Devices in the ListView. The primary key is the order number (Auftrtragsnummer) . New or changed orders are marked as unread. With the loop I want to achieve that only the displayed orders can be marked as read.

private async void miGelesen_Clicked(object sender, EventArgs e)
{
// Übergabe des Parameters NetBiosName (Transfer of the parameter NetBiosName)
var mi = ((MenuItem)sender);

         // Liste der Aufträge für dieses Gerät
         // List of Orders for one Device 
         string SQL = "select Auftragsnummer from auftrag where geraet='" + mi.CommandParameter.ToString() + "'";
         //select the order number field from the order table for one Device

         //load the data with the function get_ListAuftrage(). This is a join of 2 tables, the order table and the read table
         var liste = App.get_ListAuftraege(SQL, "select * from gelesen where neu='0'");
            
             foreach (var item in liste.ToList())
             {
                 App.set_OrderRead(item.Auftragsnummer);
             }
            
     }

Instead of the get_ListAuftraege() function, I would like to read the data from the Listview.ItemSource. My data is already there and, if necessary, filtered the way I would like it to be.

Best regards,
Michael

0 Votes 0 ·

1 Answer

JarvanZhang-MSFT avatar image
0 Votes"
JarvanZhang-MSFT answered JarvanZhang-MSFT edited

Hello,​

Welcome to our Microsoft Q&A platform!

New or changed orders are marked as unread. With the loop I want to achieve that only the displayed orders can be marked as read.

You could create a bool property in the model class to mark the item as read. And try to create two ObservableCollection<TestModel> in the viewModel class. One is used to save the data that is read from database, and the other is the 'read' data which will be shown in the listView.

Check the code:

public class TestViewModel
{
    public ObservableCollection<TestModel> DataCollection { get; set; } //store the data of database
    public ObservableCollection<TestModel> DisplayDataCollection { get; set; } //filter the data and display the data in the listview

    public TestViewModel()
    {
        DataCollection = new ObservableCollection<TestModel>();
        DisplayDataCollection = new ObservableCollection<TestModel>();
        DataCollection.CollectionChanged += DataCollection_CollectionChanged;
        //add data
    }

    //this event will be called when you add or remove items from the data collection
    private void DataCollection_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        foreach (TestModel item in e.NewItems)
        {
            item.PropertyChanged += Item_PropertyChanged;
        }

        DisplayDataCollection.Clear();
        foreach (var item in DataCollection)
        {
            if (item.IsRead)
            {
                DisplayDataCollection.Add(item);
            }
        }
    }

    //this event will be called when you modify the items of the data collection
    private void Item_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        DisplayDataCollection.Clear();
        foreach (var item in DataCollection)
        {
            if (item.IsRead)
            {
                DisplayDataCollection.Add(item);
            }
        }
    }
}

Set data binding for the listview.

//page.xaml
<ListView ItemsSource="{Binding DisplayDataCollection}">
    ...
</ListView>

//page.xaml.cs
public partial class TestPage : ContentPage
{
    TestViewModel viewModel;

    public Page3()
    {
        InitializeComponent();

        viewModel = new TestViewModel();
        BindingContext = viewModel;
    }
}


Best Regards,

Jarvan Zhang


If the response is helpful, please click "Accept Answer" and upvote it.

Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

I don't understand this approach.

Probably it is not possible to execute a loop over a ListView or the ListView-Itemsource. Then I leave the code as it is now, it works.

Best Regards,
Michael

0 Votes 0 ·

Probably it is not possible to execute a loop over a ListView or the ListView-Itemsource.

Yes, ListView doesn't provide a property to loop the items. It's hard to do that because there may many items on the screen at the same, it requires to caculate to number of the items on the screen and update the collection of the itemsSource. You could send a feature request to the product team to seek for a help on github.

0 Votes 0 ·