Xamarin forms - change page content depending on button clicked - c#

I currently have a page where I display some objects in a List view retrieved. I am using DataTemplate to display all of them because the list will grow over time. Now, for each of the object, I want to be able to display a page with some information about each of them. So, architecture will be the same for each page, but the content will be different (Labels, Title) How can I make this happen ?
Currently, each of the objects lead to the same page. I just need to display the content for each one
My object contains the following properties:
public int NewVersionId { get; set; }
public string HtmlFileName { get; set; }
public string FeatureName { get; set; }
public string Date { get; set; }
public string Description { get; set; }
public bool IsNew { get; set; }
<ui:ExtendedListView
x:Name="ListOfVersions"
Grid.Row="3"
HasUnevenRows="True"
BackgroundColor="Transparent"
ItemsSource="{Binding Path=Results}"
RowHeight="135">
<ui:ExtendedListView.ItemTemplate>
<DataTemplate x:DataType="version:NewVersionItem">
<ui:ExtendedViewCell
SelectedBackgroundColor="Transparent"
ShowSeparator="True"
Command="{Binding Path=BindingContext.ShowVersionSettingsPage, Source={Reference ListOfVersions}}"
CommandParameter="{Binding .}" >
<ui:ExtendedGrid Margin="15,20">
<ui:ExtendedGrid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</ui:ExtendedGrid.RowDefinitions>
<ui:ExtendedStackLayout
Grid.Row="0"
Orientation="Horizontal">
<ui:ExtendedLabel
x:Name="FeatureName"
HorizontalOptions="Start"
WidthRequest="300"
MaxLines="2"
Text="{Binding FeatureName}"
TextColor="{DynamicResource ForegroundColor}"
FontSize="16"
FontAttributes="Bold" />
<Frame
HorizontalOptions="Center"
WidthRequest="60"
Padding="0,0,0,0"
Margin="0,0,30,0"
CornerRadius="10"
BackgroundColor="#6AC66A"
IsVisible="{Binding IsNew}">
<ui:ExtendedLabel
Text="new"
HorizontalOptions="Center"
VerticalOptions="Center" />
</Frame>
<Image HorizontalOptions="End"
VerticalOptions="Center"
WidthRequest="{DynamicResource NavigationArrowSize}">
<Image.Source>
<FontImageSource FontFamily="GenFont"
Glyph="{controls:Icon ArrowRight}"
Size="{DynamicResource NavigationArrowSize}"
Color="{DynamicResource ForegroundColorSecondary}" />
</Image.Source>
</Image>
</ui:ExtendedStackLayout>
<ui:ExtendedLabel
Grid.Row="1"
Text="{Binding Date}"
TextColor="{DynamicResource ForegroundColor}"
FontSize="14" />
<ui:ExtendedLabel
Grid.Row="2"
Margin="0,0,0,0"
Text="{Binding Description}"
TextColor="{DynamicResource ForegroundColor}"
FontSize="14"
MaxLines="2" />
</ui:ExtendedGrid>
</ui:ExtendedViewCell>
</DataTemplate>
</ui:ExtendedListView.ItemTemplate>
</ui:ExtendedListView>
private async void OnShowVersionSettingPageExecute()
{
try
{
await NavigationService.NavigateAsync(Pages.WhatsNewFeaturePage.Id);
}
catch (Exception e)
{
Xamarin.Forms.Application.Current.Trace("An error has occurred while navigating", e, this);
}
}

Related

Getting all objects from another object based on it's id

I have 2 classes
Terms
public class Terms
{
[PrimaryKey, AutoIncrement]
public int TermId { get; set; }
public string TermName { get; set; }
public string StartDate { get; set; }
public string EndDate { get; set; }
public DateTime RealStart => DateTime.Parse(StartDate);
public DateTime RealEnd => DateTime.Parse(EndDate);
}
Courses
public class Courses
{
[PrimaryKey, AutoIncrement]
public int CourseId { get; set; }
public int TermId { get; set; }
public string CourseName { get; set; }
public string StartDate { get; set; }
public string EndDate { get; set; }
public DateTime RealStart => DateTime.Parse(StartDate);
public DateTime RealEnd => DateTime.Parse(EndDate);
public string CIName { get; set; }
public string CIEmail { get; set; }
public string CIPhone { get; set; }
public string Status { get; set; }
public bool Notifications { get; set; }
public string Notes { get; set; }
}
Term 1 -
Course 1
Course 2
When selecting a course from Term 1, I'm trying to display the expanded course details for that course.
xaml
<CollectionView x:Name="CourseCollection"
ItemsSource="{Binding Courses}"
EmptyView="No Courses to display"
SelectionMode="Single"
SelectionChanged="CourseCollection_SelectionChanged">
C#
private async void CourseCollection_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var course = (Courses)e.CurrentSelection.FirstOrDefault();
if (e.CurrentSelection != null)
{
await Navigation.PushAsync(new CoursesDetail(course));
}
}
It's displaying both courses
CoursesDetail
xaml
<CollectionView x:Name="CoursesCollection"
ItemsSource="{Binding Courses}"
EmptyView="No courses to view"
SelectionMode="Single">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Grid Padding="5" RowSpacing="1" ColumnSpacing="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" FontSize="Medium" VerticalTextAlignment="Center">Course ID</Label>
<Label Text="{Binding CourseId}" Grid.Row="0" Grid.Column="1" FontSize="Medium" x:Name="CourseId" ></Label>
<Label Grid.Row="1" Grid.Column="0" FontSize="Medium" VerticalTextAlignment="Center">Term ID</Label>
<Label Text="{Binding TermId}" Grid.Row="1" Grid.Column="1" FontSize="Medium" x:Name="TermId"></Label>
<Label Grid.Row="2" Grid.Column="0" FontSize="Medium" VerticalTextAlignment="Center">Course Name</Label>
<Label x:Name="CourseName" Grid.Row="2" Grid.Column="1" FontSize="Medium" VerticalTextAlignment="Center" Text="{Binding CourseName}"></Label>
<Label Grid.Row="3" Grid.Column="0" FontSize="Medium" VerticalTextAlignment="Center">Start Date</Label>
<Label Grid.Row="3" Grid.Column="1" FontSize="Medium" x:Name="StartDate" Text="{Binding StartDate}"></Label>
<Label Grid.Row="4" Grid.Column="0" FontSize="Medium" VerticalTextAlignment="Center">End Date</Label>
<Label Grid.Row="4" Grid.Column="1" FontSize="Medium" x:Name="EndDate" Text="{Binding EndDate}"></Label>
<Label Grid.Row="5" Grid.Column="0" FontSize="Medium" VerticalTextAlignment="Center">Instructor Name</Label>
<Label x:Name="CIName" Grid.Row="5" Grid.Column="1" FontSize="Medium" VerticalTextAlignment="Center" Text="{Binding CIName}"></Label>
<Label Grid.Row="6" Grid.Column="0" FontSize="Medium" VerticalTextAlignment="Center">Instructor Email</Label>
<Label x:Name="CIEmail" Grid.Row="6" Grid.Column="1" FontSize="Medium" VerticalTextAlignment="Center" Text="{Binding CIEmail}"></Label>
<Label Grid.Row="7" Grid.Column="0" FontSize="Medium" VerticalTextAlignment="Center">Instructor Phone</Label>
<Label x:Name="CIPhone" Grid.Row="7" Grid.Column="1" FontSize="Medium" VerticalTextAlignment="Center" Text="{Binding CIPhone}"></Label>
<Label Grid.Row="8" Grid.Column="0" FontSize="Medium" VerticalTextAlignment="Center">Course Status</Label>
<Label Grid.Row="8" Grid.Column="1" x:Name="Status" FontSize="Medium" Text="{Binding Status}"></Label>
<Label Grid.Row="9" Grid.Column="0" FontSize="Medium" VerticalTextAlignment="Center">Notes</Label>
<Label x:Name="Notes" Grid.Row="9" Grid.Column="1" FontSize="Medium" Text="{Binding Notes}"></Label>
<Label Grid.Row="10" Grid.Column="0" FontSize="Medium" VerticalTextAlignment="Center">Notifications</Label>
<Label x:Name="Notifications" Grid.Row="10" Grid.Column="1" FontSize="Medium" Text="{Binding Notifications}"></Label>
</Grid>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
c#
public partial class CoursesDetail : ContentPage
{
private readonly int _selectedCourseId;
private Courses theBiggestCourses;
protected override async void OnAppearing()
{
base.OnAppearing();
CoursesCollection.ItemsSource = await database.GetCourses(_selectedCourseId);
AssessmentsCollection.ItemsSource = await database.GetAssessments(_selectedCourseId);
}
public CoursesDetail()
{
InitializeComponent();
}
public CoursesDetail(Courses courses)
{
_selectedCourseId = courses.CourseId;
InitializeComponent();
this.theBiggestCourses = courses;
}
I've tried manually passing through each text field through the constructor. I have sample data that should auto populate and thought that it was the issue, but I removed those methods and tried manually added a Term, Courses for that Term but as soon as it gets to more than 1 course, it wacks out.
EDIT - My pea sized brain theory could be that since Terms is getting passed through as an object, capturing all the elements of that object, that it's still holding onto that Term object, so when calling the Courses object, it's capturing all the courses objects for that terms object. I hope I explained that decent.
EDIT2 - GET COURSES
public static async Task<IEnumerable<Courses>> GetCourses(int termId)
{
await Init();
var courses = await db.Table<Courses>()
.Where(i => i.TermId == termId).ToListAsync();
return courses;
}
public static async Task<IEnumerable<Courses>> GetCourses()
{
await Init();
var courses = await db.Table<Courses>().ToListAsync();
return courses;
}
These are the two for GetCourses. Is it because we're passing through an int termId here and an object in the method through the constructor? Then it defaults to the unparameterized constructor, which is going to return all of them?
GetCourses expects a TermID
public static async Task<IEnumerable<Courses>> GetCourses(int termId)
{
await Init();
var courses = await db.Table<Courses>()
.Where(i => i.TermId == termId).ToListAsync();
return courses;
}
but when you call it you are passing a CourseID
CoursesCollection.ItemsSource = await database.GetCourses(_selectedCourseId);

Row set in 'Auto' takes me all the screen even if it is blank

In a CollectionView I have 4 rows, 2 of which are set to "Auto".
In one I have a Label in Binding, in the other I have another CollectionView with objects in Binding. In the Row where I have the Label, the height is automatically set correctly, while where I have the CollectionView it becomes an "infinite" height, in the sense that even if empty, it takes up the whole screen.
<DataTemplate>
<yummy:PancakeView CornerRadius="5" BackgroundColor="Transparent">
<Grid BackgroundColor="Gainsboro" RowSpacing="0.2">
<Grid.RowDefinitions>
<RowDefinition Height="21"/>
<RowDefinition Height="16"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3"/>
<ColumnDefinition Width="65"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<BoxView Grid.Column="0" Grid.RowSpan="4" BackgroundColor="{Binding ColoreUmore}"/>
<Label Grid.Row="0" Grid.Column="2" Text="{Binding GiornoTrascritto}" FontSize="14" TextColr="Gray" Margin="0,5,0,0"/>
<Label Grid.Row="1" Grid.Column="2" Text="{Binding Orario}" FontSize="14" TextColr="Gray"/>
<Image Grid.Row="0" Grid.RowSpan="3" Grid.Column="1" Margin="8" Source="{Binding Umore}" VerticalOptions="Start" HeightRequest="45"/>
<Label Grid.Row="3" Grid.Column="2" TextColor="Black" FontSize="16" Text="{Binding Nota}" Margin="0,0,10,0" VerticalOptions="Start" HorizontalTextAlignment="Start" VerticalTextAlignment="Start"/>
<CollectionView
Grid.Row="2"
Margin="0,0,10,0"
Grid.Column="2"
SelectionMode="None"
ItemsSource="{Binding IconDiaries}"
VerticalOptions="Start">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical" VerticalItemSpacing="5" HorizontalItemSpacing="5"/>
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid RowSpacing="0.5">
<Grid.RowDefinitions>
<RowDefinition Height="17"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="18"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<BoxView BackgroundColor="Gray" Grid.ColumnSpan="2" Grid.Row="0" CornerRadius="5" Opacity="0.6" />
<Image Grid.Row="0" Grid.Column="0" Source="{Binding isSource}" Margin="3"/>
<Label Grid.Row="0" Grid.Column="1" Text="{Binding id}" TextColor="Black" FontSize="12" VerticalTextAlignment="Center" Margin="0,0,3,0"/>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
</yummy:PancakeView>
</DataTemplate>
while where I have the CollectionView it becomes an "infinite" height, in the sense that even if empty, it takes up the whole screen.
From your code and description, you have one collectionview in datatemplate, now you want to adjust collectionview height according to its content, am I right?
If yes, I suggest you can binding collectionview HeightRequest like the following code:
<StackLayout >
<CollectionView
x:Name="assessmentsCollectionView"
BackgroundColor="Blue"
HeightRequest="{Binding rowHeigth}"
ItemsSource="{Binding letters}">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Padding="5" Spacing="10">
<Frame
Padding="0"
CornerRadius="5"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<StackLayout Orientation="Horizontal">
<Frame
Padding="5"
CornerRadius="0"
WidthRequest="50">
<Label
FontSize="24"
HorizontalTextAlignment="Center"
Text="{Binding TypeLetter}"
TextColor="#37474f"
VerticalTextAlignment="Center" />
</Frame>
<StackLayout Padding="10">
<Label
FontSize="24"
Text="{Binding Name}"
TextColor="Black" />
<StackLayout Orientation="Horizontal">
<Image
HeightRequest="12"
Source="c1.png"
WidthRequest="12" />
<Label
FontSize="12"
Text="{Binding Date}"
TextColor="Gray" />
</StackLayout>
</StackLayout>
</StackLayout>
</Frame>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<Button
x:Name="btn1"
Command="{Binding AddCommand}"
Text="btn1" />
</StackLayout>
public partial class Page4 : ContentPage
{
public Page4()
{
InitializeComponent();
this.BindingContext = new letterviewmodel(); ;
}
}
public class letterviewmodel: INotifyPropertyChanged
{
public ObservableCollection<lettermodel> letters { get; set; }
private int _rowHeigth;
public int rowHeigth
{
get { return _rowHeigth; }
set
{
_rowHeigth = value;
RaisePropertyChanged("rowHeigth");
}
}
public ICommand AddCommand { protected set; get; }
public letterviewmodel()
{
letters = new ObservableCollection<lettermodel>()
{
new lettermodel(){TypeLetter="A",Name="letter 1",Date="2021-01-01"},
new lettermodel(){TypeLetter="B",Name="letter 2",Date="2021-01-01"},
new lettermodel(){TypeLetter="C",Name="letter 3",Date="2021-01-01"}
};
rowHeigth = letters.Count * 100 ;
AddCommand = new Command<lettermodel>(async (key) => {
letters.Add(new lettermodel() { TypeLetter = "D", Name = "test letter ", Date = "2021-01-01" });
rowHeigth = letters.Count * 100 ;
});
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public class lettermodel
{
public string TypeLetter { get; set; }
public string Name { get; set; }
public string Date { get; set; }
}
The screenshot:
If I understand correctly, you want the CollectionView to take an automatic height and adapt to the row, right?
In order to make this happen you will need to:
Set the property
ItemSizingStrategy="MeasureFirstItem" in the CollectionView, so the CollectionView has the proper height you're looking for.
Set the Row Height to *, so the CollectionView height sets automatically for the remaining size of the page.
Set VerticalOptions to FillAndExpand in Collection View so the CollectionView can adapt to the size of the Row.
Finally, put the label with Row 3 below the CollectionView to avoid any issues with the Layout order.
Let me know if this does any help!

Is it possible to get the group key of the Selected Item in a CollectionView with IsGrouped=true and a CollectionView.GroupHeaderTemplate in C#

I am using a collectionview in a xamarin.Forms app. I want to identify the Group Key of a SelectedItem.
The items in each group are not unique. Item can appear in multiple groups. Perhaps I could use SelectionChangedCommand and specify the CommandParameter as the label.text in the GroupHeaderTemplate?
It is possible.
Based on Xamarin.Forms - CollectionView, we could use SelectionChanged method to get the curren selected item. Then we can loop which group contain this item, therefore the property of Group also will get.
We will modifl VerticalListEmptyGroupsPage.Xaml code as follows:
<StackLayout Margin="20">
<CollectionView ItemsSource="{Binding Animals}"
SelectionChanged="CollectionView_SelectionChanged"
SelectionMode="Single"
IsGrouped="true">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Image Grid.RowSpan="2"
Source="{Binding ImageUrl}"
Aspect="AspectFill"
HeightRequest="60"
WidthRequest="60" />
<Label Grid.Column="1"
Text="{Binding Name}"
FontAttributes="Bold" />
<Label Grid.Row="1"
Grid.Column="1"
Text="{Binding Location}"
FontAttributes="Italic"
VerticalOptions="End" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
<CollectionView.GroupHeaderTemplate>
<DataTemplate>
<Label Text="{Binding Name}"
BackgroundColor="LightGray"
FontSize="Large"
FontAttributes="Bold" />
</DataTemplate>
</CollectionView.GroupHeaderTemplate>
<CollectionView.GroupFooterTemplate>
<DataTemplate>
<Label Text="{Binding Count, StringFormat='Total animals: {0:D}'}"
Margin="0,0,0,10" />
</DataTemplate>
</CollectionView.GroupFooterTemplate>
</CollectionView>
</StackLayout>
And VerticalListEmptyGroupsPage.xaml.cs:
public partial class VerticalListEmptyGroupsPage : ContentPage
{
static GroupedAnimalsViewModel groupedAnimals;
public VerticalListEmptyGroupsPage()
{
InitializeComponent();
groupedAnimals= new GroupedAnimalsViewModel(true);
BindingContext = groupedAnimals;
}
private void CollectionView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Animal selectedAnimal = e.CurrentSelection[0] as Animal;
foreach (var animals in groupedAnimals.Animals)
{
foreach(var animal in animals)
{
if(animal == selectedAnimal)
{
Console.WriteLine(animals.Name);
DisplayAlert("Group Name", animals.Name, "OK");
}
}
}
}
}
The effect:
===============================Update====================================
If there are multi groups contain the same Item, I think the best way is to design the model of item with containing the Group key.
For example, the Animal model could be designed as follows:
public class Animal
{
public string GroupKey { set; get; }
public string Name { get; set; }
public string Location { get; set; }
public string Details { get; set; }
public string ImageUrl { get; set; }
public override string ToString()
{
return Name;
}
}
This way is similar with the foreign key of database.

Binding individual property based of sqlite local database

I have created a ListView with items based on data saved in database. Its computer list with few properties as name, ipAdress, port and selected. If selected = true computer is marked as default and I need to change his appearance in ListView.
I need to create a binding to property which isnt part of the table.
I have simple list of computers (XAML)
<ListView x:Name="CompListView" HasUnevenRows="true" Grid.Row="1" SeparatorColor="Black" ItemsSource="{Binding ComputerList}"
SelectedItem="{Binding SelectedComputerItem, Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Text="{Binding ComputerName}" Grid.Row="1" Font="20" TextColor="{Binding Selected_Color}" />
<Label Text="{Binding IPAddress}" Grid.Row="0" Font="20" Grid.Column="1" HorizontalOptions="EndAndExpand" HorizontalTextAlignment="End" TextColor="{Binding Selected_Color}"/>
<Label Text="{Binding Port}" Grid.Row="1" Font="13" Grid.Column="1" HorizontalOptions="EndAndExpand" HorizontalTextAlignment="End" TextColor="{Binding Selected_Color}"/>
<Image Source="computerpng.png" Grid.Row="0" Grid.Column="0" WidthRequest = "24" HeightRequest = "24" HorizontalOptions = "Start"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Base computer View connected to database.
public class BaseComputerView : INotifyPropertyChanged
{
public Computer _computer;
public INavigation _navigation;
public IComputer _computerRepository;
public string ComputerName
{
get => _computer.ComputerName;
set
{
_computer.ComputerName = value;
NotifyPropertyChanged("Computer_Name");
}
}
public string IPAddress
{
get => _computer.IPAddress;
set
{
_computer.IPAddress = value;
NotifyPropertyChanged("IPAddress");
}
}
public string Port
{
get => _computer.Port;
set
{
_computer.Port = value;
NotifyPropertyChanged("Port");
}
}
public bool Selected
{
get => _computer.Selected;
set
{
_computer.Selected = value;
NotifyPropertyChanged("Selected");
}
}
Based on _Selected I added property "Selected_Color" within the same class. Goal is to change back color of controls if the item is selected.
public string Selected_Color
{
get
{
string Text_Color = string.Empty;
try
{
if (Selected == true)
{
Text_Color = "#33cc33";
}
else
{
Text_Color = "#000000";
}
}
catch (Exception ex)
{
return "#000000";
}
return Text_Color;
}
}
This code however looks up for property "Selected_Color" in Computer table, which is wrong.
use the Ignore attribute to tell SQLite to ignore your new property
[Ignore]
public string Selected_Color
alternately, you could use a ValueConverter to set the color based on the Selected property
Thanks for your answer,
I figured it out by adding Selected_Color as Computer Table property.
[Table("Computer")]
public class Computer
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public string ComputerName { get; set; }
public string IPAddress { get; set; }
public string Port { get; set; }
public bool Selected { get; set; }
[Ignore]
public string Selected_Color
{
get
{
string Text_Color = string.Empty;
try
{
if (Selected == true)
{
//Green color
Text_Color = "#33cc33";
}
else
{
Text_Color = "#000000";
}
}
catch (Exception ex)
{
return "#000000";
}
return Text_Color;
}
}
}
App_ComputerList_Image
Works fine until I open one of the computers for edit and come back to computer list. What is weird is fact that I get Java exception not for the first time I do that but only for the second time. So I am able to open one of the items and came back to computer list. If I repeat that then I get this Java exception.
just wanted to add answer for everyone who would fight with similar problem, that I found a better way to do this. You can define data templates based on your property and then use it to draw your Listview like this. Difference in this case is textcolor of the labels.
<ResourceDictionary>
<DataTemplate x:Key="SelectedComputer">
<ViewCell>
<Grid Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Text="{Binding ComputerName}" Grid.Row="1" Font="20" TextColor="Green" />
<Label Text="{Binding IPAddress}" Grid.Row="0" Font="20" Grid.Column="1" HorizontalOptions="EndAndExpand" HorizontalTextAlignment="End" TextColor="Green"/>
<Label Text="{Binding Port}" Grid.Row="1" Font="13" Grid.Column="1" HorizontalOptions="EndAndExpand" HorizontalTextAlignment="End" TextColor="Green"/>
<Image Source="computerpng.png" Grid.Row="0" Grid.Column="0" WidthRequest = "24" HeightRequest = "24" HorizontalOptions = "Start"/>
</Grid>
</ViewCell>
</DataTemplate>
<DataTemplate x:Key="Computer">
<ViewCell>
<Grid Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Text="{Binding ComputerName}" Grid.Row="1" Font="20" TextColor="Black" />
<Label Text="{Binding IPAddress}" Grid.Row="0" Font="20" Grid.Column="1" HorizontalOptions="EndAndExpand" HorizontalTextAlignment="End" TextColor="Black"/>
<Label Text="{Binding Port}" Grid.Row="1" Font="13" Grid.Column="1" HorizontalOptions="EndAndExpand" HorizontalTextAlignment="End" TextColor="Black"/>
<Image Source="computerpng.png" Grid.Row="0" Grid.Column="0" WidthRequest = "24" HeightRequest = "24" HorizontalOptions = "Start"/>
</Grid>
</ViewCell>
</DataTemplate>
<local:ComputerTemplateSelector x:Key="ComputerTemplateSelector" SelectedComputer="{StaticResource SelectedComputer}" Computer="{StaticResource Computer}" />
</ResourceDictionary>
Template selector:
public class ComputerTemplateSelector : DataTemplateSelector
{
public DataTemplate SelectedComputer { get; set; }
public DataTemplate Computer { get; set; }
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
return ((SQLite_Database.Computer)item).Selected == true ? SelectedComputer : Computer;
}
}

Collection was modified; enumeration operation may not execute. Xamarin Forms

I have a list view in Xamarin Froms Project as :
<ListView x:Name="ExerciseList" HasUnevenRows="False" SeparatorVisibility="None" RowHeight="200">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Vertical">
<StackLayout Orientation="Horizontal" HorizontalOptions="CenterAndExpand">
<Entry Text="{Binding ExerciseName}" HorizontalTextAlignment="Center" Focused="ExerciseName_Focused" HorizontalOptions="CenterAndExpand">
<Entry.GestureRecognizers>
<TapGestureRecognizer Tapped="ExerciseNameGestureRecognizer_Tapped"/>
</Entry.GestureRecognizers>
</Entry>
<Image IsVisible="{Binding GreenVisible}" Source="smallgreenadd.png"/>
<Image IsVisible="{Binding RedVisible}" Source="smallredremove.png"/>
</StackLayout>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Label Text="Sets : " Grid.Column="0" Grid.Row="0" HorizontalTextAlignment="Center" HorizontalOptions="CenterAndExpand" />
<Label Text="Weights : " Grid.Column="0" Grid.Row="1" HorizontalTextAlignment="Center" HorizontalOptions="CenterAndExpand" />
<Label Text="Reps: " Grid.Column="0" Grid.Row="2" HorizontalTextAlignment="Center" HorizontalOptions="CenterAndExpand" />
<Entry Text="{Binding Sets}" Grid.Column="1" Grid.Row="0" HorizontalTextAlignment="Center" HorizontalOptions="CenterAndExpand" />
<Entry Text="{Binding Weights}" Grid.Column="1" Grid.Row="1" HorizontalTextAlignment="Center" HorizontalOptions="CenterAndExpand" />
<Entry Text="{Binding Reps}" Grid.Column="1" Grid.Row="2" HorizontalTextAlignment="Center" HorizontalOptions="CenterAndExpand" />
</Grid>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
This is attached to a View Modal called ExerciseViewModal. This is:
public class ExerciseViewModal : BaseViewModal
{
private List<AddExerciseModal> _addExerciseModals;
public List<AddExerciseModal> AddExerciseModals
{
get { return _addExerciseModals; }
set
{
_addExerciseModals = value;
OnPropertyChanged("AddExerciseModals");
}
}
public ExerciseViewModal()
{
_addExerciseModals = new List<AddExerciseModal>();
if (AddExerciseModals.Count == 0)
{
for (int i = 0; i < 7; i++)
{
AddExerciseModal addExerciseModal = new AddExerciseModal
{
ExerciseID = i,
ExerciseName = "Excercise " + i,
GreenVisible = false,
RedVisible = true,
Sets = "2",
Reps = "10",
Weights = "10"
};
AddExerciseModals.Add(addExerciseModal);
}
AddExerciseModals[AddExerciseModals.Count - 1].GreenVisible = true;
AddExerciseModals[AddExerciseModals.Count - 1].RedVisible = false;
}
}
}
AddExerciseModal class :
public class AddExerciseModal
{
public int ExerciseID { get; set; }
public string ExerciseName { get; set; }
public string Weights { get; set; }
public string Reps { get; set; }
public string Sets { get; set; }
public bool GreenVisible { get; set; }
public bool RedVisible { get; set; }
}
Whenever I try to change the sets/reps/Weights property inside the ListView I always get an error saying:
"Collection was modified; enumeration operation may not execute."
How can I solve this?
Can you change your List to ObservableCollection and try it .That will resolve the problem.

Categories