Bas H
Bas H

Reputation: 2216

ToList in MainViewModel

In a ViewModel i load data from a FirebaseDatabase and showing it in a CollectionView.

     public MainViewModel()
        {
            var collection = firebase
               .Child("Foto/")
               .AsObservable<Fotos>()
               .Subscribe((dbevent) =>
               {
                   if (dbevent.Object != null)
                   {
                       Foto.Add(dbevent.Object);
                   }
               });
        }

But i want to change it ToList so i make it Descending based on BalId in the Database.

Want to use GetAllFotosDesending() but i cannot make it work in the MainViewModel.

  public async Task<List<Fotos>> GetAllFotosDesending()
    {
        return (await firebase
          .Child("Foto/")
          .OnceAsync<Fotos>()).Select(item => new Fotos
          {
              BalId = item.Object.BalId,
              RollNo = item.Object.RollNo,
              Foto = item.Object.Foto,
              Titel = item.Object.Titel,
              Fototekst = item.Object.Fototekst
          }).OrderByDescending(x => x.BalId).ToList();
    }

2 options , or make it ToList in the MainViewModel or add GetAllFotosDesending() work in the MainViewModel. The last option is maybe better ? but i cannot make this working when adding to the MainViewModel

This is the CollectionView with ItemsSource="{Binding Foto}"

   <CollectionView 
        x:Name="Dood"
        ItemsSource="{Binding Foto}">
        <CollectionView.ItemTemplate>
            <DataTemplate>
                <Grid ColumnDefinitions="Auto, *"
                      RowDefinitions="Auto, Auto, Auto, 1"
                      ColumnSpacing="10"
                      RowSpacing="5"
                      Padding="0,10">

                    <Image Source="{Binding Pic}"
                           Margin="20,0,0,10"
                            HeightRequest="70"
                            WidthRequest="70"
                            HorizontalOptions="Center"
                            VerticalOptions="Center"
                            Grid.RowSpan="3"
                            Grid.Row="0"
                            Grid.Column="0">
                        <Image.Clip>
                            <EllipseGeometry
                                        Center="35,35"
                                        RadiusX="35"
                                        RadiusY="35"/>
                        </Image.Clip>
                    </Image>

                    <Label Text="{Binding Titel}"
                           FontAttributes="Bold"
                           Grid.Column="1"
                           Grid.Row="0"/>

                    <Label Text="{Binding Email}"
                           Grid.Column="1"
                           Grid.Row="1"/>

                    <Label Text="{Binding RollNo}"
                           Grid.Column="1"
                           Grid.Row="2"/>

                    <BoxView Style="{StaticResource SeparatorLine}"
                             Grid.Column="0"
                             Grid.Row="3"
                             Grid.ColumnSpan="2"/>
                </Grid>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>

Binding like this

 public MainPage()
    {
        InitializeComponent();
        BindingContext = new MainViewModel();
    }

Upvotes: 0

Views: 71

Answers (2)

FreakyAli
FreakyAli

Reputation: 16439

OrderBy does not have Alphanumeric comparison by default, the default Orderby only compares Alphabets or Numbers not a combination of both to handle this you need to create your own Alphanumeric Comparator that does this for you (especially if these are string values)

You can use this basic comparator for both Ascending and Descending orders:

public class AlphanumComparator : IComparer<object>
{
    private enum ChunkType { Alphanumeric, Numeric };

    private bool InChunk(char ch, char otherCh)
    {
        ChunkType type = ChunkType.Alphanumeric;

        if (char.IsDigit(otherCh))
        {
            type = ChunkType.Numeric;
        }

        return (type != ChunkType.Alphanumeric || !char.IsDigit(ch))
            && (type != ChunkType.Numeric || char.IsDigit(ch));
    }

    public int Compare(object x, object y)
    {
        string firstString = x as string;
        string secondString = y as string;
        if (string.IsNullOrWhiteSpace(firstString) || string.IsNullOrWhiteSpace(secondString))
        {
            return 0;
        }

        int firstMarker = 0, secondMarker = 0;

        while ((firstMarker < firstString.Length) || (secondMarker < secondString.Length))
        {
            if (firstMarker >= firstString.Length)
            {
                return -1;
            }
            else if (secondMarker >= secondString.Length)
            {
                return 1;
            }
            char firstCh = firstString[firstMarker];
            char secondCh = secondString[secondMarker];

            StringBuilder thisChunk = new StringBuilder();
            StringBuilder thatChunk = new StringBuilder();

            while ((firstMarker < firstString.Length) && (thisChunk.Length == 0 || InChunk(firstCh, thisChunk[0])))
            {
                thisChunk.Append(firstCh);
                firstMarker++;

                if (firstMarker < firstString.Length)
                {
                    firstCh = firstString[firstMarker];
                }
            }

            while ((secondMarker < secondString.Length) && (thatChunk.Length == 0 || InChunk(secondCh, thatChunk[0])))
            {
                thatChunk.Append(secondCh);
                secondMarker++;

                if (secondMarker < secondString.Length)
                {
                    secondCh = secondString[secondMarker];
                }
            }

            int result = 0;
            // If both chunks contain numeric characters, sort them numerically
            if (char.IsDigit(thisChunk[0]) && char.IsDigit(thatChunk[0]))
            {
                int thisNumericChunk = Convert.ToInt32(thisChunk.ToString());
                int thatNumericChunk = Convert.ToInt32(thatChunk.ToString());
                if (thisNumericChunk < thatNumericChunk)
                {
                    result = -1;
                }

                if (thisNumericChunk > thatNumericChunk)
                {
                    result = 1;
                }
            }
            else
            {
                result = thisChunk.ToString().CompareTo(thatChunk.ToString());
            }

            if (result != 0)
            {
                return result;
            }
        }

        return 0;
    }
}

Once you are done, you use it like below:

OrderByDescending(x => x.BalId, new AlphanumComparator());
OrderBy(x => x.BalId, new AlphanumComparator());

Upvotes: 1

Bas H
Bas H

Reputation: 2216

Solved like it this.

 public async Task<List<Fotos>> GetAllFotosDesending()
    {
        return (await firebase
          .Child("Foto/")
          .OnceAsync<Fotos>()).Select(item => new Fotos
          {
              BalId = item.Object.BalId,
              RollNo = item.Object.RollNo,
              Foto = item.Object.Foto,
              Titel = item.Object.Titel,
              Fototekst = item.Object.Fototekst
          }).OrderByDescending(x => x.BalId).ToList();
    }
    public async void InitializeAsync()
    {          
        Fotos = await GetAllFotosDesending();           
    }
  

        public MainViewModel()
    {
        InitializeAsync();
    }
              

Upvotes: 0

Related Questions