Reputation: 2216
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
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
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