ListView ItemSource ObservableRangeCollection<> accessing Model ObservableRangeCollection<> - c#

I'm developing an .NET Xamarin App. I want to list all Products as ItemTemplate in the Grouped-ListView and Invoice.Name as Header. Currently I only get the GroupHeaderTemplate shown in my Grouped-ListView.
Model: Invoice.cs
public class Invoice : ObservableRangeCollection<Invoice>
{
public string Name { get; set; }
public Company Company { get; set; }
public ObservableRangeCollection<Product> Products { get; set; }
}
Model: Products.cs
public class Product : ObservableRangeCollection<Product>
{
public string Name { get; set; }
public DateTime ExpireDate { get; set; }
}
ViewModel: MainViewVM (creating fake data)
public ObservableRangeCollection<Invoice> Invoices { get; set; }
public MainViewVM()
{
Invoices.Add(new Invoice { Name = "Test1", Company = new Company { Image = image }, Products = new ObservableRangeCollection<Product>() { new Product { Name = "ProductTest1", CreatedDate = DateTime.Now }, new Product { Name = "ProductTest2", CreatedDate = DateTime.Now } } });
Invoices.Add(new Invoice { Name = "Test2", Company = new Company { Image = image }, Products = new ObservableRangeCollection<Product>() { new Product { Name = "ProductTest3", CreatedDate = DateTime.Now }, new Product { Name = "ProductTest4", CreatedDate = DateTime.Now } } });
}
View: MainViewVM (ListView)
<ListView
IsGroupingEnabled="True"
ItemsSource="{Binding Invoices}">
<ListView.GroupHeaderTemplate>
<DataTemplate x:DataType="models:Invoice">
<ViewCell>
<StackLayout Orientation="Horizontal" VerticalOptions="Center" HorizontalOptions="Center">
<Image Source="{Binding Company.Image}" WidthRequest="66" VerticalOptions="Center"/>
<Label Text="{Binding Name}" VerticalOptions="Center"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate x:DataType="models:Product">
<ViewCell>
<StackLayout VerticalOptions="Center">
<Label Text="{Binding Name}" VerticalOptions="Center"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>

I added a constructor with : base. That fixed it for me.
https://learn.microsoft.com/de-de/xamarin/xamarin-forms/user-interface/collectionview/grouping
public Invoice(string name, Company company, ObservableRangeCollection<Product> products) : base(products)
{
Name = name;
Company = company;
Products = products;
}

Related

xamarin forms dependent dropdown using local json data and multiple item selection

in my xamarin forms application registration part i need to fill profession and expertise field from a local json.The profession field is a dropdown and then expertise is also a dropdown and subpart of profession.From expertise field i need to select minimum one and maximum 3 options.
ProfessionalRegistrationPage.xaml.cs
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ProfessionalRegistrationPage : ContentPage
{
public List<Profession> professions { get; set; }
public List<Profession> expertises { get; set; }
public ProfessionalRegistrationPage()
{
InitializeComponent();
professions = GetJsonDataProfession();
BindingContext = this;
professionPicker.ItemsSource = professions;
professionPicker.SelectedItem = professions[0];
}
private List<Profession> GetJsonDataProfession()
{
string jsonFileName = "profession.json";
ProfessionList ObjProfessionList = new ProfessionList();
var assembly = typeof(MainPage).GetTypeInfo().Assembly;
Stream stream = assembly.GetManifestResourceStream($"{ assembly.GetName().Name}.{ jsonFileName}");
using (var reader = new StreamReader(stream))
{
var jsonString = reader.ReadToEnd();
ObjProfessionList = JsonConvert.DeserializeObject<ProfessionList>(jsonString);
}
return ObjProfessionList.professions;
}
private void professionPicker_SelectedIndexChanged(object sender, EventArgs e)
{
Picker picker = (Picker)sender;
int selectedIndex = picker.SelectedIndex;
if (selectedIndex != -1)
{
expertises = professions[selectedIndex].expertises;
expertisePicker.ItemsSource = expertises;
expertisePicker.SelectedItem = expertises[0];
}
}
}
public partial class ProfessionList
{
[JsonProperty("professions")]
public List<Profession> professions { get; set; }
}
public partial class Profession
{
[JsonProperty("expertises")]
public List<Profession> expertises { get; set; }
[JsonProperty("professionname")]
public string ProfessionName { get; set; }
[JsonProperty("expertisename")]
public string ExpertiseName { get; set; }
}
ProfessionalRegistrationPage.xaml
<StackLayout Orientation="Vertical">
<Label Text="Profession"
TextColor="{StaticResource BackgroundGradientStart}">
</Label>
<Frame BackgroundColor="Transparent"
BorderColor="{StaticResource BackgroundGradientStart}"
Padding="0"
Margin="10"
CornerRadius="15"
HorizontalOptions="FillAndExpand">
<Picker
x:Name="professionPicker"
SelectedIndexChanged="professionPicker_SelectedIndexChanged"
ItemDisplayBinding="{Binding ProfessionName}"
ItemsSource="{Binding profession}"
TextColor="{StaticResource White}"/>
</Frame>
</StackLayout>
<StackLayout Orientation="Vertical">
<Label Text="Expertise"
TextColor="{StaticResource BackgroundGradientStart}">
</Label>
<Frame
BackgroundColor="Transparent"
BorderColor="{StaticResource BackgroundGradientStart}"
Padding="0"
Margin="10"
CornerRadius="15"
HorizontalOptions="FillAndExpand">
<Picker x:Name="expertisePicker"
ItemDisplayBinding="{Binding ExpertiseName}"
ItemsSource="{Binding profession}"
TextColor="{StaticResource White}"/>
</Frame>
</StackLayout>
profession.json
{
"professions": [
{
"professionname": "Doctor",
"expertises": [
{
"expertisename": "Pediatric"
},
{
"expertisename": "Ortho"
}
]
},
{
"professionname": "Engineer",
"expertises": [
{
"expertisename": "Software"
},
{
"expertisename": "Civil"
}
]
}
]
}
i used picker here.but picker doesnot support more than one item selection.
otherwise its works perfectly.
i think i need to place a popup and in pop up page i need to fix a listview and checkbox. but i dont now how to do that. I am new to xamarin.

Scroll a CollectionView to ItemGroup

I have a CollectionView with groups. Each group has a string with a Date.
I subsequently created a CarouselView with all the dates of the CollectionView groups.
I am trying to create a way to scroll the elements of the CarouselView and consequently scroll the CollectionView to the corresponding group, but it doesn't work.
The CollectionView remains stationary.
<CollectionView x:Name="CollectionDiary"....../>
c#
public class HumorGroup : ObservableCollection<HumorDiary>
{
public string Name { get; private set; }
public HumorGroup(string name, ObservableCollection<HumorDiary> icon) : base(icon)
{
Name = name;
}
}
public ObservableCollection<HumorGroup> TotHumor { get; private set; } = new ObservableCollection<HumorGroup>();
HumorGroup group = new HumorGroup("Month" + " " + Year, new ObservableCollection<HumorDiary>());
TotHumor.Add(group);
group.Add(item HumorDiary);
private void ScrollCollectionView_Clicked(object sender, EventArgs e)
{
var current = CarouselView.CurrentItem as HumorGroup;
CollectionDiary.ScrollTo(current, position: ScrollToPosition.Start);
}
I am trying to create a way to scroll the elements of the CarouselView and consequently scroll the CollectionView to the corresponding group, but it doesn't work.
I agree with Jason's opinion, you can let CollectionView to scroll to the first item for current group in the CarouselView_Scrolled event.
private void CarouselView_Scrolled(object sender, ItemsViewScrolledEventArgs e)
{
var current = CarouselView1.CurrentItem as HumorGroup;
if(current!=null)
{
CollectionDiary.ScrollTo(current.FirstOrDefault(),ScrollToPosition.Center);
}
}
I do one sample that you can take a look:
<StackLayout>
<CarouselView
x:Name="CarouselView1"
ItemsSource="{Binding humors}"
Scrolled="CarouselView_Scrolled">
<CarouselView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Label Text="{Binding Name}" />
</StackLayout>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
<CollectionView
x:Name="CollectionDiary"
HeightRequest="100"
IsGrouped="True"
ItemsSource="{Binding humors}"
SelectionMode="Single">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Orientation="Horizontal">
<Label Text="{Binding name}" />
<Label Text="{Binding count}" />
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
<CollectionView.GroupHeaderTemplate>
<DataTemplate>
<Label
BackgroundColor="LightGray"
FontAttributes="Bold"
FontSize="Large"
Text="{Binding Name}" />
</DataTemplate>
</CollectionView.GroupHeaderTemplate>
</CollectionView>
</StackLayout>
public partial class Page8 : ContentPage
{
public GroupHumorViewmodel groups { get; set; }
public Page8()
{
InitializeComponent();
groups = new GroupHumorViewmodel();
this.BindingContext =groups;
}
private void CarouselView_Scrolled(object sender, ItemsViewScrolledEventArgs e)
{
var current = CarouselView1.CurrentItem as HumorGroup;
if(current!=null)
{
CollectionDiary.ScrollTo(current.FirstOrDefault(),ScrollToPosition.Center);
}
}
}
public class HumorDiary
{
public string name { get; set; }
public int count { get; set; }
}
public class HumorGroup:ObservableCollection<HumorDiary>
{
public string Name { get; set; }
public HumorGroup(string name, ObservableCollection<HumorDiary> humor) : base(humor)
{
Name = name;
}
}
public class GroupHumorViewmodel
{
public ObservableCollection<HumorGroup> humors { get; set; }
public GroupHumorViewmodel()
{
humors = new ObservableCollection<HumorGroup>();
humors.Add(new HumorGroup("2021",new ObservableCollection<HumorDiary>() {
new HumorDiary(){name="2021-day1",count=3},
new HumorDiary(){name="2021-day2",count=3},
new HumorDiary(){name="2021-day3",count=4},
new HumorDiary(){name="2021-day4",count=2},
new HumorDiary(){name="2021-day5",count=5},
new HumorDiary(){name="2021-day6",count=4},
new HumorDiary(){name="2021-day7",count=2},
new HumorDiary(){name="2021-day8",count=5}
}));
humors.Add(new HumorGroup("2020", new ObservableCollection<HumorDiary>() {
new HumorDiary(){name="2020-day1",count=3},
new HumorDiary(){name="2020-day2",count=3},
new HumorDiary(){name="2020-day3",count=4},
new HumorDiary(){name="2020-day4",count=2},
new HumorDiary(){name="2020-day5",count=5},
new HumorDiary(){name="2020-day6",count=4},
new HumorDiary(){name="2020-day7",count=2},
new HumorDiary(){name="2020-day8",count=5}
}));
humors.Add(new HumorGroup("2019", new ObservableCollection<HumorDiary>() {
new HumorDiary(){name="2019-day1",count=3},
new HumorDiary(){name="2019-day2",count=3},
new HumorDiary(){name="2019-day3",count=4},
new HumorDiary(){name="2019-day4",count=2},
new HumorDiary(){name="2019-day5",count=5},
new HumorDiary(){name="2019-day6",count=4},
new HumorDiary(){name="2019-day7",count=2},
new HumorDiary(){name="2019-day8",count=5}
}));
}
}

Xamarin - Grouping List Views

I've got some issues with grouping my List Views.
When I isgroupingenabled = "true" my List only shows the groupDisplayBinding name.
I've read and tried so many things and wasn't able to apply them to my project I need your help now.
I've seen I need to put an Observablecollection but don't know where and how to do it.
My Model
public class League
{
public string name { get; set; }
public string country { get; set; }
public string logo { get; set; }
public string flag { get; set; }
}
public class HomeTeam
{
public int team_id { get; set; }
public string team_name { get; set; }
public string logo { get; set; }
}
public class AwayTeam
{
public int team_id { get; set; }
public string team_name { get; set; }
public string logo { get; set; }
}
public class Score
{
public string halftime { get; set; }
public string fulltime { get; set; }
public string extratime { get; set; }
public string penalty { get; set; }
}
public class Fixture
{
public int fixture_id { get; set; }
public int league_id { get; set; }
public League league { get; set; }
public DateTime event_date { get; set; }
public int event_timestamp { get; set; }
public int? firstHalfStart { get; set; }
public int? secondHalfStart { get; set; }
public string round { get; set; }
public string status { get; set; }
public string statusShort { get; set; }
public int elapsed { get; set; }
public string venue { get; set; }
public string referee { get; set; }
public HomeTeam homeTeam { get; set; }
public AwayTeam awayTeam { get; set; }
public int? goalsHomeTeam { get; set; }
public int? goalsAwayTeam { get; set; }
public Score score { get; set; }
}
public class Api
{
public int results { get; set; }
public List<Fixture> Fixtures { get; set; }
}
public class RootFixtures
{
public Api api { get; set; }
}
My JSON : (Part of it)
{"api": {
"results": 162,
"fixtures": [
{
"fixture_id": 234670,
"league_id": 900,
"league": {
"name": "Division 1",
"country": "Saudi-Arabia",
"logo": null,
"flag": "https://media.api-sports.io/flags/sa.svg"
},
"event_date": "2020-03-10T00:00:00+00:00",
"event_timestamp": 1583798400,
"firstHalfStart": null,
"secondHalfStart": null,
"round": "Regular Season - 28",
"status": "Match Postponed",
"statusShort": "PST",
"elapsed": 0,
"venue": "Prince Saud bin Jalawi Stadium (al-Khobar (Khobar))",
"referee": null,
"homeTeam": {
"team_id": 2933,
"team_name": "Al-Qadisiyah FC",
"logo": "https://media.api-sports.io/teams/2933.png"
},
"awayTeam": {
"team_id": 2928,
"team_name": "Al Khaleej Saihat",
"logo": "https://media.api-sports.io/teams/2928.png"
},
"goalsHomeTeam": null,
"goalsAwayTeam": null,
"score": {
"halftime": null,
"fulltime": null,
"extratime": null,
"penalty": null
}
}
]
}
}
ListMatchPage :
public partial class ListMatchs : ContentPage
{
string JsonLeagues = "The Json Below"
public ListMatchs()
{
InitializeComponent();
var Leagues = JsonConvert.DeserializeObject<RootFixtures>(JsonLeagues);
LeaguesList.ItemsSource = Leagues.api.Fixtures;
}
}
I'm new at dev and here I Hope my english wasn't too bad.
edit :
MyXAML :
<ContentPage.Content>
<StackLayout>
<Label Text="Futurs matchs" HorizontalTextAlignment="Center" />
<ListView x:Name="LeaguesList" GroupDisplayBinding="{Binding Path=League.name}"
GroupShortNameBinding="{Binding Path=League.name}"
IsGroupingEnabled="True" HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell Height="30">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Aspect="AspectFit" Source="{Binding Path=homeTeam.logo}" />
<Label Grid.Column="1" VerticalOptions="CenterAndExpand" HorizontalTextAlignment="Center" TextColor="Black" FontSize="15" FontAttributes="Bold" Text="{Binding Path=homeTeam.team_name}" HorizontalOptions="CenterAndExpand"/>
<Label Grid.Column="2" VerticalOptions="CenterAndExpand" HorizontalTextAlignment="Center" TextColor="Black" FontSize="15" FontAttributes="Bold" Text="{Binding Path=awayTeam.team_name}" HorizontalOptions="CenterAndExpand"/>
<Image Grid.Column="3" Aspect="AspectFit" Source="{Binding Path=awayTeam.logo}" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
#JackHUA here is what I did :
XAML.CS :
ObservableCollection<groupedfix> FixturesCollection = new ObservableCollection<groupedfix>();
public ListMatchs()
{
InitializeComponent();
var Leagues = JsonConvert.DeserializeObject<RootFixtures>(JsonLeagues);
foreach (var match in Leagues.api.Fixtures)
{
int fixtureid = match.fixture_id;
DateTime fixturedate = match.event_date;
int FixtureLeagueid = match.league_id;
string FixtureLeague = match.league.name;
string FixtureLeaguelogo = match.league.logo;
string Hometeamname = match.homeTeam.team_name;
string Hometeamlogo = match.homeTeam.logo;
string Awayteamname = match.awayTeam.team_name;
string Awayteamlogo = match.awayTeam.logo;
HomeTeam HOMETEAM = new HomeTeam() { team_name = Hometeamname, logo = Hometeamlogo };
AwayTeam AWAYTEAM = new AwayTeam() { team_name = Awayteamname, logo = Awayteamlogo };
League LEAGUE = new League() { logo = FixtureLeaguelogo, name = FixtureLeague };
Fixture MATCH = new Fixture() { fixture_id = fixtureid, event_date = fixturedate, league_id = FixtureLeagueid, league = LEAGUE, homeTeam = HOMETEAM, awayTeam = AWAYTEAM };
groupedfix GROUPEDFIX = new groupedfix(FixtureLeague) { MATCH };
FixturesCollection.Add(GROUPEDFIX);
}
LeaguesList.ItemsSource = FixturesCollection;
}
public class groupedfix : List<Fixture>
{
public string FixtureLeague { get; set; }
public groupedfix(string Name )
{
FixtureLeague = Name;
}
}
XAML :
<ContentPage.Content>
<StackLayout>
<Label Text="Futurs matchs" HorizontalTextAlignment="Center" />
<ListView x:Name="LeaguesList" GroupDisplayBinding="{Binding FixtureLeague}"
IsGroupingEnabled="True" HasUnevenRows="True" ItemTapped="Newgameclick">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell Height="30">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Aspect="AspectFit" Source="{Binding Path=homeTeam.logo}"/>
<Label Grid.Column="1" VerticalOptions="CenterAndExpand" HorizontalTextAlignment="Center" TextColor="Black" FontSize="15" FontAttributes="Bold" Text="{Binding Path=homeTeam.team_name}" HorizontalOptions="CenterAndExpand"/>
<Label Grid.Column="2" VerticalOptions="CenterAndExpand" HorizontalTextAlignment="Center" TextColor="Black" FontSize="15" FontAttributes="Bold" Text="{Binding Path=awayTeam.team_name}" HorizontalOptions="CenterAndExpand"/>
<Image Grid.Column="3" Aspect="AspectFit" Source="{Binding Path=awayTeam.logo}" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
The image result :
See the pic
But when I change
LeaguesList.ItemsSource = FixturesCollection;
in
LeaguesList.ItemsSource = FixturesCollection.GroupBy(F => F.FixtureLeague);
I get this : See the pic
With error :
[0:] Binding:'FixtureLeague' property not found on 'System.Linq.Grouping`2[System.String,BeastTIPS.Pages.ListMatchs+groupedfix]'...
[0:] Binding: 'homeTeam' property not found on 'BeastTIPS.Pages.ListMatchs+groupedfix'...
[0:] Binding: 'awayTeam' property not found on 'BeastTIPS.Pages.ListMatchs+groupedfix'...
The List is groupedby but my Binding are not found
I can't find what property to Bind.
The model you added to the ItemsSource should in a right format as the document mentioned, I wrote a example for you and you can check the code:
public partial class MainPage : ContentPage
{
ObservableCollection<myModel> FixtureCollection = new ObservableCollection<myModel>();
public MainPage()
{
InitializeComponent();
League LeagueOne = new League() { name = "one" };
League LeagueTwo = new League() { name = "two" };
League LeagueThree = new League() { name = "three" };
HomeTeam HomeTeamOne = new HomeTeam() { team_name = "HomeTeamOne" };
HomeTeam HomeTeamTwo = new HomeTeam() { team_name = "HomeTeamTwo" };
HomeTeam HomeTeamThree = new HomeTeam() { team_name = "HomeTeamThree" };
AwayTeam AwayTeamOne = new AwayTeam() { team_name = "AwayTeamOne" };
AwayTeam AwayTeamTwo = new AwayTeam() { team_name = "AwayTeamTwo" };
AwayTeam AwayTeamThree = new AwayTeam() { team_name = "AwayTeamThree" };
Fixture FixtureOne = new Fixture() { league = LeagueOne, homeTeam = HomeTeamOne, awayTeam = AwayTeamOne};
Fixture FixtureTwo = new Fixture() { league = LeagueTwo, homeTeam = HomeTeamTwo, awayTeam = AwayTeamTwo };
Fixture FixtureThree = new Fixture() { league = LeagueThree, homeTeam = HomeTeamThree, awayTeam = AwayTeamThree };
myModel myModelOne = new myModel(FixtureOne.league.name) { FixtureOne };
myModel myModelTwo = new myModel(FixtureTwo.league.name) { FixtureTwo };
myModel myModelThree = new myModel(FixtureThree.league.name) {FixtureThree };
FixtureCollection.Add(myModelOne);
FixtureCollection.Add(myModelTwo);
FixtureCollection.Add(myModelThree);
LeaguesList.ItemsSource = FixtureCollection;
BindingContext = this;
}
}
public class myModel : List<Fixture>
{
public string name { get; set; }
public myModel( string Name) {
name = Name;
}
}
And in code behind:
<StackLayout>
<Label Text="Futurs matchs" HorizontalTextAlignment="Center" />
<ListView x:Name="LeaguesList"
GroupDisplayBinding="{Binding name}"
GroupShortNameBinding="{Binding name}"
IsGroupingEnabled="True" HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell Height="30">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Aspect="AspectFit" Source="{Binding Path=homeTeam.logo}" />
<Label Grid.Column="1" VerticalOptions="CenterAndExpand" HorizontalTextAlignment="Center" TextColor="Black" FontSize="15" FontAttributes="Bold" Text="{Binding Path=homeTeam.team_name}" HorizontalOptions="CenterAndExpand"/>
<Label Grid.Column="2" VerticalOptions="CenterAndExpand" HorizontalTextAlignment="Center" TextColor="Black" FontSize="15" FontAttributes="Bold" Text="{Binding Path=awayTeam.team_name}" HorizontalOptions="CenterAndExpand"/>
<Image Grid.Column="3" Aspect="AspectFit" Source="{Binding Path=awayTeam.logo}" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
I also uploaded my sample project here and feel free to ask me any question.
Update:
I think what you really need is OrderBy not GroupBy:
LeaguesList.ItemsSource = FixturesCollection.OrderBy(f => f.FixtureLeague).ToList();
When you use GroupBy, you can set a breakpoint right there to check the LeaguesList.ItemsSource, you will find the structure has been change, the count of LeaguesList.ItemsSource becomes 56.
There is another problem in your xaml, the GroupDisplayBinding should bind to FixtureLeague not name:
<ListView x:Name="LeaguesList" GroupDisplayBinding="{Binding FixtureLeague}"

Missing list view details when refreshing

I have a list that list all of my customers. I refresh the list when I typed something in my search box. My problem is when I type something the list became unstable meaning the details for example the customer name is missing in some parts of the list.
I will show you what I mean.
This what the list looked like upon loading:
Image :
This is what the list looked like when I tapped the item (I refreshed the list when I tapped an item) or search something:
Now here is my code to list the page.
Here is my XAML Code:
<ListView SeparatorVisibility="Default" x:Name="lstActivity" ItemSelected="LstActivity_ItemSelected" ItemTapped="LstActivity_ItemTapped" HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Frame StyleClass="lstframe" CornerRadius="0" BorderColor="Transparent" HasShadow="False">
<StackLayout StyleClass="lstContainer" VerticalOptions="CenterAndExpand">
<Grid>
<Label VerticalTextAlignment="Center" StyleClass="lstActivityName" VerticalOptions="Center" Grid.Row="0" Grid.Column="0" Text="{Binding ActivityDescription}">
<Label.FontFamily>
<OnPlatform x:TypeArguments="x:String">
<On Platform="Android" Value="SFProDisplay-Regular.ttf#SFProDisplay-Regular"/>
</OnPlatform>
</Label.FontFamily>
</Label>
<Switch VerticalOptions="Center" Grid.Row="0" Grid.Column="1" IsEnabled="False" IsToggled="{Binding Selected}" />
</Grid>
</StackLayout>
</Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Here is my XAML.cs Code:
public void List_Activity()
{
try
{
var keyword = entSearchActivity.Text;
if (String.IsNullOrEmpty(keyword))
{
var query = DefaultSettings.conn.QueryAsync<ActivityTable>("SELECT ActivityDescription, ActivityID, Selected FROM tblActivity ORDER BY ActivityDescription LIMIT 20");
var resultCount = query.Result.Count;
if (resultCount > 0)
{
lstActivity.IsVisible = true;
result = query.Result;
lstActivity.ItemsSource = result;
}
else
{
lstActivity.IsVisible = false;
}
}
else
{
var query = DefaultSettings.conn.QueryAsync<ActivityTable>("SELECT ActivityDescription, ActivityID, Selected FROM tblActivity WHERE ActivityDescription LIKE '%" + keyword +"%' ORDER BY ActivityDescription LIMIT 20");
var resultCount = query.Result.Count;
if (resultCount > 0)
{
lstActivity.IsVisible = true;
result = query.Result;
lstActivity.ItemsSource = result;
}
else
{
lstActivity.IsVisible = false;
}
}
}
catch (Exception ex)
{
Crashes.TrackError(ex);
}
}
And here is my ActivityTable.cs:
[Table("tblActivity")]
public class ActivityTable
{
[PrimaryKey]
public string ActivityID { get; set; }
public string ActivityDescription { get; set; }
public string RecordLog { get; set; }
public DateTime LastSync { get; set; }
public DateTime LastUpdated { get; set; }
public int Deleted { get; set; }
public int Checked { get; set; }
public int Finished { get; set; }
public bool Selected { get; set; }
}
My questions are:
What is/are the cause(s) of this?
How can I avoid this in the future?

Display master detail data in nested ListBox

I want to display my data like this
Here is the class definition:
public class Order
{
public string Customer { get; set; }
public decimal Amount { get; set; }
public List<OrderDetail> Details = new List<OrderDetail>();
}
public class OrderDetail
{
public string Product { get; set; }
public int Qty { get; set; }
}
I try to use ListBox but fail to display Details. Below is my try in xaml:
<ListBox x:Name="lstOrder">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Customer}"/>
<TextBlock Text="{Binding Amount}"/>
<ListBox ItemsSource="{Binding Details}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Product}"/>
<TextBlock Text="{Binding Qty}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
in code behind:
public MainWindow()
{
InitializeComponent();
List<Order> OrderList = new List<Order>();
Order order = new Order { Customer = "David", Amount = 2000 };
order.Details.Add(new OrderDetail { Product = "A", Qty = 5 });
OrderList.Add(order);
order = new Order { Customer = "John", Amount = 5000 };
order.Details.Add(new OrderDetail { Product = "A", Qty = 2 });
order.Details.Add(new OrderDetail { Product = "B", Qty = 3 });
OrderList.Add(order);
lstOrder.ItemsSource = OrderList;
}
What is the correct way to bind OrderList.Details? Any suggestions will be appreciated.
In your Order class Details is a field not a property. Binding to fields is not supported.
You can modify the class slightly so it becomes:
public class Order
{
public string Customer { get; set; }
public decimal Amount { get; set; }
List<OrderDetail> details;
public List<OrderDetail> Details { get { return details; } }
public Order()
{
details = new List<OrderDetail>();
}
}
And then it will bind correctly.

Categories