What is the best way to bind data in ListView?

felipedrtfelipedrt USMember ✭✭

Hello!

I'm using SQLite with Xamarin.Forms and I need to binding a huge data into a listview, It's almost 16.000 register.

What is the best way to do this? Using IEnumerable, ObservableCollection, List?

What is the best way to use ItemTemplate, create a class, inherited with ViewCell, or using XAML?

This is my model:

`[Table("tbPROD")]
public class E_PROD : EntidadeBase, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this,
new PropertyChangedEventArgs(propertyName));
}

    //

    #region Atributos

    private string _PROD_Id = string.Empty;
    private string _PROD_Codigo = string.Empty;
    private int _PROD_SQEM_Id = 0;
    private string _PROD_Descricao = string.Empty;
    private string _PROD_UnidadeVenda = string.Empty;
    private string _PROD_UnidadeEstoque = string.Empty;
    private int _PROD_Ordem = 0;
    private decimal _PROD_Valor = 0;

    #endregion

    #region Propriedades

    [PrimaryKey]
    public string PROD_Id
    {
        get
        {
            return _PROD_Id;
        }

        set
        {
            _PROD_Id = value;
            OnPropertyChanged(nameof(PROD_Id));
        }
    }

    [NotNull]
    [Default(false, "")]
    [MaxLength(15)]
    public string PROD_Codigo
    {
        get
        {
            return _PROD_Codigo;
        }
        set
        {
            _PROD_Codigo = value;
            OnPropertyChanged(nameof(PROD_Codigo));
        }
    }

    [NotNull]
    [Default(false, 0)]
    public int PROD_SQEM_Id
    {
        get
        {
            return _PROD_SQEM_Id;
        }

        set
        {
            _PROD_SQEM_Id = value;
            OnPropertyChanged(nameof(PROD_SQEM_Id));
        }
    }

    [MaxLength(40)]
    [NotNull]
    [Default(false, "")]
    public string PROD_Descricao
    {
        get
        {
            return _PROD_Descricao;
        }
        set
        {
            _PROD_Descricao = value;
            OnPropertyChanged(nameof(PROD_Descricao));
        }
    }

    [MaxLength(3)]
    [NotNull]
    [Default(false, "")]
    public string PROD_UnidadeVenda
    {
        get
        {
            return _PROD_UnidadeVenda;
        }
        set
        {
            _PROD_UnidadeVenda = value;
            OnPropertyChanged(nameof(PROD_UnidadeVenda));
        }
    }

    [MaxLength(3)]
    [NotNull]
    [Default(false, "")]
    public string PROD_UnidadeEstoque
    {
        get
        {
            return _PROD_UnidadeEstoque;
        }
        set
        {
            _PROD_UnidadeEstoque = value;
            OnPropertyChanged(nameof(PROD_UnidadeEstoque));
        }
    }

    [NotNull]
    [Default(false, 0)]
    public int PROD_Ordem
    {
        get
        {
            return _PROD_Ordem;
        }

        set
        {
            _PROD_Ordem = value;
            OnPropertyChanged(nameof(PROD_Ordem));
        }
    }

    public decimal PROD_Valor
    {
        get
        {
            return _PROD_Valor;
        }

        set
        {
            _PROD_Valor = value;
            OnPropertyChanged(nameof(PROD_Valor));
        }
    }

    #endregion
}`

Here is my "select":
public IEnumerable GetProdutos()
{
lock (collisionLock)
{
var query = (from cust in database.Table()
select cust);

            return query;
        }
    }

Answers

  • NMackayNMackay GBInsider, University mod

    16000 ?????

    The user will never be able to sign their own name again after scrolling that list.....

    I generally use ObservableCollection

    I recommend using the SQLite async API though as so need to keep fetching that amount of the UI thread and be awaitable.

  • felipedrtfelipedrt USMember ✭✭

    I make some tests with ObservableCollection, but the "select" in ths SQLite, it's to slow.

    This is normal for the number of records?

  • felipedrtfelipedrt USMember ✭✭

    What should I do with this? I need to show these records.

    And SQLite it's too slow with this, ListView is too slow to perform record by record, how I proceed with this?

    Thx guys!

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭
    Why you should visualize 16000 records? First of all you have to filter them
  • felipedrtfelipedrt USMember ✭✭

    I don't need to visualize 16000 records, but I need to load this records.

    I'm doing this, load an ObservableCollection with all these recrods (16000, here is the problem it's too SLOW), and after this, i'm adding 10 records on a new ObsevableCollection to show in ListView.

    After scrolling, I'll show more 10 records, follow my code:

    private int tamanhoPagina = 10; private ObservableCollection<PROD> ListCollection = new ObservableCollection<PROD>(); private ObservableCollection<PROD> ListTela = new ObservableCollection<PROD>();

    `//load all records
    private async Task Popular_ListPROD_Collection(string valor)
    {
    if (ListTela != null)
    ListTela.Clear();

            ListCollection = pPROD.Value.ListPROD_Collection(valor);
    
            if (pPROD.Value.HasError)
            {
                await DisplayAlert("Erro", "Erro ao listar produtos!\n" + pPROD.Value.MsgError, "OK");
            }
            else
            {
                if (ListCollection.Count == 0)
                {
                    svListView.IsVisible = false;
                    stkPainelInferior.IsVisible = false;
                    imgWarning.IsVisible = true;
                }
                else
                {
                    Popular_lvwPROD();
                }
            }
        }`
    

    `private void Popular_lvwPROD()
    {
    for (int i = 0; i < tamanhoPagina; i++)
    {
    if (i < ListCollection.Count)
    ListTela.Add(ListCollection[i]);
    else
    break;
    }

            //
    
            svListView.IsVisible = true;
            stkPainelInferior.IsVisible = true;
            imgWarning.IsVisible = false;
    
            lvwProdutos.ItemTemplate = new DataTemplate(typeof(PROD_FormattingCells));
            lvwProdutos.ItemsSource = ListTela;
            lvwProdutos.SeparatorVisibility = SeparatorVisibility.Default;
            lvwProdutos.SeparatorColor = Color.Black;
            lvwProdutos.HasUnevenRows = true;
            lvwProdutos.RowHeight = 55;
    
            lblQtdRegistros.Text = ListCollection.Count > 0 ?
                "aprox. " + ListCollection.Count.ToString() + (ListCollection.Count == 1 ? " registro." : " registros.") : string.Empty;
        }`
    

    `private void lvwProdutos_ItemAppearing(object sender, ItemVisibilityEventArgs e)
    {
    if (listTela == null)
    return;

            var itemMostradoTela = pPROD;
    
            var ultimoItem = listTela[listTela.Count - 1];
            var primeiroItem = listTela[0];
    
            if (itemMostradoTela == ultimoItem)
            {
                var posicaoAtual = listGrandona.IndexOf(itemMostradoTela) + 1;
                for (int i = posicaoAtual; i < posicaoAtual + tamanhoPagina; i++)
                {
                    if (i >= 0 && i < listGrandona.Count)
                    {
                        listTela.Add(listGrandona[i]);
                    }
                }
            }
    

    }`

  • felipedrtfelipedrt USMember ✭✭

    It's kind an infinte list, but it's not working as well ;/

  • Gigex42Gigex42 USMember ✭✭✭✭
    edited August 2017

    I think the best way to provide this amount of records is to use paging within your api an not in the app where its already to late.

    When you load, start your request you should also send the current "page". When you hit the last item of your listview you can load the next page.

  • felipedrtfelipedrt USMember ✭✭

    @Gigex42 It's a good idea!

    Do you have some example of how to do this?

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭
    I think you can read 10 records at time from SQLite.


    Here some help

    http://motzcod.es/post/107620279512/load-more-items-at-end-of-listview-in
  • felipedrtfelipedrt USMember ✭✭

    @AlessandroCaliaro this is nice! But the ObservableCollection shoul be with all my data?

  • Gigex42Gigex42 USMember ✭✭✭✭

    In the example from @AlessandroCaliaro is everything you need.

    On start he creates the ObservableCollection and binds it to the listview.

    In the LoadItems method he loads the next items and adds them to the ObservableCollection.

  • felipedrtfelipedrt USMember ✭✭

    @Gigex42 OK, I understand this, but the ObservableCollection must to be with all my data?

    I need to load 16k records on ObservableCollection?

    Where I load my data?

    Sorry, but I do not understand this, because, if i'm going to load 16k records into the ObservableCollection, it's going to continue slow.

    This is my problem, SQLite it's to slow to load these records here.

    Thx!

  • Gigex42Gigex42 USMember ✭✭✭✭

    You can choose what ever you want to keep the data. Mostly I use the ObservableCollection so thats fine.

    I dont think SQLite is the problem that its to slow. Downloading 16k records at once is the problem.
    Im not really in SQLite but do you save these records on the device or do you load these from some server.

  • felipedrtfelipedrt USMember ✭✭

    @Gigex42 Yeah,I'm using ObservableCollection too.

    If I release the db3 file from SQLite can you make a test for me? Maybe I'm doing something wrong.

    Thx!

Sign In or Register to comment.