Xamarin forms: System.InvalidCastException: 'Specified cast is not valid - c#

I have a listview in xamarin and when i try to cast the selecteditem in a button clicked event it gives me the error. The class SavedVira is for a sqlite database table, i'm trying to use async but it seems to have been more trouble then worth. (i'm very new to programing). Here is my code:
XAML:
<ListView x:Name="SavedViraView" HasUnevenRows="True" ItemTapped="SavedViraView_ItemTapped">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout Padding="10">
<Label Text="Navn:" FontSize="18" FontAttributes="Bold"/>
<Label Text="{Binding Virusnavn}" FontSize="15"/>
<Label Text="Symptomer:" FontSize="18" FontAttributes="Bold"/>
<Label Text="{Binding symptom1}"/>
<Label Text="{Binding symptom2}"/>
<Label Text="{Binding symptom3}"/>
<Label Text="{Binding symptom4}"/>
<Label Text="{Binding symptom5}"/>
<Label Text="{Binding symptom6}"/>
<Label Text="Lavet af:" FontSize="18" FontAttributes="Bold"/>
<Label Text="{Binding Creator}"/>
<Button Text="Load" x:Name="LoadButton" Clicked="LoadButton_Clicked"/>
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
XAML.CS:
private ObservableCollection<SavedVira> SavedVira = new ObservableCollection<SavedVira>();
public Åben()
{
InitializeComponent();
}
protected override void OnAppearing()
{
nameLabel.Text = Values.currentUser;
Init();
}
private async void Init()
{
BindingContext = new SavedVira();
var Viralist = await DataServices.GetSavedVira();
SavedVira = new ObservableCollection<SavedVira>(Viralist);
SavedViraView.ItemsSource = SavedVira;
}
private void LoadButton_Clicked(object sender, EventArgs e)
{
var LoadVirus = ((ListView)sender).SelectedItem as SavedVira;
if (LoadVirus == null)
return;
Values.LoadBool = true;
Values.symptomZero = LoadVirus.symptom1;
Values.symptomOne = LoadVirus.symptom2;
Values.symptomTwo = LoadVirus.symptom3;
Values.symptomThree = LoadVirus.symptom4;
Values.symptomFour = LoadVirus.symptom5;
Values.symptomFive = LoadVirus.symptom6;
}
SavedVira cast/model:
[Table("savedvira")]
public class SavedVira
{
[PrimaryKey, AutoIncrement]
[Column("id")]
public int Id { get; set; }
[Column("virusnavn")]
public string Virusnavn { get; set; }
[Column("creator")]
public string Creator { get; set; }
[Column("symptoms1")]
public string symptom1 { get; set; }
[Column("symptoms2")]
public string symptom2 { get; set; }
[Column("symptoms3")]
public string symptom3 { get; set; }
[Column("symptoms4")]
public string symptom4 { get; set; }
[Column("symptoms5")]
public string symptom5 { get; set; }
[Column("symptoms6")]
public string symptom6 { get; set; }
}
Any help would be grealty appriciated!

the sender is a Button so this doesn't work
var LoadVirus = ((ListView)sender).SelectedItem as SavedVira;
instead do this
var btn = (Button)sender;
var selected = (SavedVira)btn.BindingContext;
also, using the same name for an instance variable and a class is confusing, I'd suggest you avoid it
SavedVira = new ObservableCollection<SavedVira>(Viralist);

Related

How to create a UI with horizontal and vertical scrolling in xamarin forms

I have a design with vertical and horizontal scrolling.I need to add two lists in to the same page.So I have used bindable layout for this but the scrolling is not working on this. Please help me on the below. I am stuck on this for a week.
Here is my View and ViewModel
<StackLayout BackgroundColor="WhiteSmoke">
<Grid ColumnDefinitions="*,*" RowDefinitions="Auto,*,Auto">
<StackLayout
Grid.Row="0"
Grid.Column="1"
BindableLayout.ItemsSource="{Binding ListSource.TestList2}"
Orientation="Horizontal"
VerticalOptions="FillAndExpand">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Label
Margin="0" WidthRequest="75"
FontSize="16"
HeightRequest="58"
HorizontalOptions="FillAndExpand"
MaxLines="3"
Text="{Binding Subname}"
VerticalOptions="FillAndExpand"
VerticalTextAlignment="Center" />
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
<StackLayout x:Name="layout1"
Grid.Row="1" Margin="30,0,0,0"
Grid.Column="0" Grid.ColumnSpan="2"
BindableLayout.ItemsSource="{Binding ListSource.TestList}"
Orientation="Vertical">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Grid ColumnDefinitions="*,*">
<Label
Grid.Column="0"
Margin="3"
Text="{Binding name}" />
<StackLayout
Grid.Column="1"
Margin="0"
BindableLayout.ItemsSource="{Binding classes}"
HorizontalOptions="FillAndExpand"
Orientation="Horizontal">
<BindableLayout.ItemTemplate>
<DataTemplate>
<StackLayout Orientation="Horizontal">
<RadioButton WidthRequest="75"
HorizontalOptions="FillAndExpand"
IsChecked="{Binding IsFailed}"/>
<Entry Placeholder="Subject"
IsVisible="{Binding IsEntry}"/>
</StackLayout>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</Grid>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</Grid>
</StackLayout>
ViewModel
public class ListViewVM:BaseViewModel
{
private TestClass _listSource;
public TestClass ListSource
{
get { return _listSource; }
set { _listSource = value;
OnPropertyChanged("ListSource");
}
}
//public
public ListViewVM()
{
TestClass kk=new TestClass();
kk.BindData();
ListSource = new TestClass();
ListSource.TestList =new List<TestName>(kk.TestList);
ListSource.TestList2= new List<TestSubject>( kk.TestList2);
ListSource.TestList.ForEach(x => x.classes=kk.TestList2);
var item = ListSource;
}}
Model
public class TestClass
{
public List<TestName> TestList { get; set; }
public List<TestSubject> TestList2 { get; set; }
public void BindData()
{
TestList = new List<TestName>() { new TestName {id=1,name="Jo"},
new TestName {id=2,name="Annie" },
new TestName {id=3,name="Alex" }};
TestList2 = new List<TestSubject>() { new TestSubject { id=1,Subname="Maths"},
new TestSubject { id=2,Subname="Physics"},
new TestSubject { id=2,Subname="Chemestry"},
new TestSubject { id=2,Subname="Other",IsEntry=true}};
}
}
public class TestName
{
public int id { get; set; }
public string name { get; set; }
public List<TestSubject> classes { get; set; }
}
public class TestSubject
{
public int id { get; set; }
public string Subname { get; set; }
public bool IsFailed {get;set;}
public bool IsOthersSelected { get; set; }
public bool IsEntry { get; set; }
}
Current UI
Some conditions is there , the user should select only one option from each row, but in my design they can select multiple option. If I add the RadioButton without that stacklayout the selection case is working but that time I cannot add the Entry field.If the user select "other" , then I need display an input field at the end along with "other" option for adding the other subject . So that field also mandatory for me.

how to bind a viewmodel variable to ObservableCollection items in xamarin form?

I have a list of tasks that I need to bind a Boolean variable to its item.
the task object includes a completedDate property that if it has value defines the task as completed.
on the view, I need to check if it has value the button text display the text: "mark as incomplete"
----Task Object-----
public class ProjectTaskLineItemSummary
{
public int TenantId { get; set; }
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal? CostMultiplier { get; set; }
public DateTimeOffset? CompletedDate { get; set; }
public int? CompletedByUserId { get; set; }
}
-------viewmodel-------
viewmodel()
{
public ObservableCollection<ProjectTaskLineItemSummary> Tasks { get; set; }
...
bool isCompleted;
public bool IsCompleted
{
get {
return isCompleted;
}
set
{
isCompleted = value;
OnPropertyChanged();
}
}
}
-----view----
<CollectionView Grid.Row="1" ItemsSource="{Binding Tasks}" x:Name="List3">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid>
<Frame
Margin="0,10"
Padding="10"
BackgroundColor="{StaticResource PrimaryWhite}"
BorderColor="{StaticResource PrimaryLightGray}"
CornerRadius="10"
HasShadow="False">
<Grid RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto" RowSpacing="15">
<StackLayout HorizontalOptions="EndAndExpand" Orientation="Horizontal">
<Image
HeightRequest="20"
Source="iconCalender.png"
WidthRequest="20" />
<Label
FontFamily="{StaticResource MeduimFont}"
Style="{StaticResource LabelMedium}"
Text="{Binding CompletedDate,StringFormat='{0:MMMM dd, yyyy}'}"
TextColor="{StaticResource PrimaryBlack}"
/>
</StackLayout>
</StackLayout>
<BoxView
Grid.Row="1"
HeightRequest="1"
Color="{StaticResource PrimaryLightGray}" />
<Label
Grid.Row="2"
Style="{StaticResource LabelMedium}"
Text="{Binding Name}"
TextColor="{StaticResource PrimaryBlack}" />
<Button
x:Name="lstbtnMarkasComplite"
Grid.Row="5"
Padding="15,0"
Clicked="MarkTaskAsCompletedClicked"
CornerRadius="20"
FontSize="{StaticResource Font12}"
HeightRequest="40"
CommandParameter="{Binding Id}"
HorizontalOptions="CenterAndExpand"
Style="{StaticResource ButtonPurple}"
Text="Mark as Completed" >
<Button.Triggers>
<DataTrigger TargetType="Button" Binding="{Binding IsCompleted}" Value="True">
<Setter Property="Text" Value="Mark Task as In Completed"/>
</DataTrigger>
</Button.Triggers>
</Button>
</Grid>
</Frame>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
I tried to assign it in view model like below but it doesn't work:
public override async Task InitializeAsync(object navigationData)
{
await SetBusyAsync(async () =>
{
...
Tasks = ObjectMapper.Map<ObservableCollection<ProjectTaskLineItemSummary>>(project.TaskLineItems);
foreach (var task in Tasks)
{
isCompleted = task.CompletedDate.HasValue ? true : false;
}
RaisePropertyChanged(() => Model);
RaisePropertyChanged(() => Notes);
RaisePropertyChanged(() => Files);
RaisePropertyChanged(() => Tasks);
});
}
This could simply be achieved by Binding Text Property of the button and then dynamically set the Text of the button based on the CompletedDate of the entity.
Below is the code snippets for your reference:
Model:
ProjectTaskLineItemSummary.cs
public class ProjectTaskLineItemSummary
{
public int TenantId { get; set; }
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal? CostMultiplier { get; set; }
public DateTimeOffset? CompletedDate { get; set; }
public int? CompletedByUserId { get; set; }
public string CompletedButton { get; set; }
}
View:
<CollectionView ItemsSource="{Binding Tasks}" x:Name="List3" Background="aqua">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid>
<Frame Margin="0,10" Padding="10" HasShadow="False">
<Grid RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto" RowSpacing="15">
<StackLayout HorizontalOptions="EndAndExpand" Orientation="Horizontal">
<Image HeightRequest="30" Source="XamarinLogo.png" WidthRequest="80" />
<Label x:Name="mydate" Text="{Binding CompletedDate,StringFormat='{0:MMMM dd, yyyy}'}" TextColor="Black"/>
</StackLayout>
<BoxView Grid.Row="1" HeightRequest="1" Color="Black" />
<Label Grid.Row="2" Text="{Binding Name}" TextColor="Black" />
<Button Grid.Row="5" x:Name="lstbtnMarkasComplite" Padding="15,0"
Clicked="MarkTaskAsCompletedClicked"
CornerRadius="20"
Text="{Binding CompletedButton}"
FontSize="Medium"
HeightRequest="40"
CommandParameter="{Binding Id}"
HorizontalOptions="CenterAndExpand">
</Button>
</Grid>
</Frame>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
ViewModel:
public class PageViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public ObservableCollection<ProjectTaskLineItemSummary> Tasks { get; set; }
bool isCompleted { get; set; }
public bool IsCompleted
{
get => isCompleted;
set
{
isCompleted = value;
PropertyChanged?.Invoke(this,
new PropertyChangedEventArgs(nameof(IsCompleted)));
}
}
string completed { get; set; }
public String CompletedButton
{
get => completed;
set
{
completed = value;
PropertyChanged?.Invoke(this,
new PropertyChangedEventArgs(nameof(CompletedButton)));
}
}
public PageViewModel()
{
Tasks = new ObservableCollection<ProjectTaskLineItemSummary>()
{
new ProjectTaskLineItemSummary(){TenantId = 1, Id =1, Name = "jobs ", Description= "jjjj",CostMultiplier=1 ,CompletedDate =DateTime.UtcNow, CompletedByUserId=1 ,CompletedButton = ""},
new ProjectTaskLineItemSummary(){TenantId = 2, Id =2, Name = "james ",Description= "aaaa",CostMultiplier=2 , CompletedByUserId=2,CompletedButton = "" },
new ProjectTaskLineItemSummary(){TenantId = 3, Id =3, Name = "rollex ",Description= "rrrr",CostMultiplier=3 ,CompletedDate =DateTime.UtcNow, CompletedByUserId=3 ,CompletedButton = ""}
};
setButtonIsCompleted();
}
private void setButtonIsCompleted()
{
foreach (var task in Tasks)
{
if (task.CompletedDate == null)
{
task.CompletedButton = "Mark Task as Completed";
}
else
{
task.CompletedButton = "Mark Task as inCompleted";
}
}
}
}

Xamarin Forms - DataTemplate from Nested Property within DataTemplate from Parent Object

I have 3 classes which are named Users, Cards, and BindingUser which is a class to bind them together.
public class User
{
public int Uid { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class CardData
{
public int _id { get; set; }
public string CardName { get; set; }
public string CardNote { get; set; }
}
public class BindingUser
{
public User bUser { get; set; }
public ObservableCollection<CardData> cardDatas { get; set; }
public BindingUser()
{
cardDatas = new ObservableCollection<CardData>();
}
}
I am trying to create a Horizontal stack layout, filled with frames for each user and in each frame is a list of cards belonging to that user.
I have tried doing this with listviews, stacklayouts and pretty much every other method google shows but each has the same result.
I get the frames for users, but they aren't populated.
My xaml looks like this, I know this is wrong but I formatted it like this to show what I am trying to achieve. In this example, the FirstName and LastName are working fine but the listviews aren't being populated.
<ContentPage.Content>
<StackLayout Orientation="Horizontal" BackgroundColor="#EBEBEB" HeightRequest="130" BindableLayout.ItemsSource="{Binding bindingUsers}" WidthRequest="410">
<BindableLayout.ItemTemplate>
<DataTemplate>
<StackLayout HeightRequest="300" VerticalOptions="Start" Orientation="Vertical">
<Frame CornerRadius="0"
HorizontalOptions="Start"
VerticalOptions="Start"
Margin="0"
Padding="0"
WidthRequest="410"
HeightRequest="80"
BackgroundColor="Red"
HasShadow="true">
<StackLayout Orientation="Vertical">
<Label Text="{Binding bUser.FirstName}"/>
<Label Text="{Binding bUser.LastName}"/>
</StackLayout>
</Frame>
<StackLayout Orientation="Vertical" BackgroundColor="Blue">
<ListView BindableLayout.ItemsSource="{Binding bindingUsers.cardDatas}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label Text ="{Binding CardName}"/>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</StackLayout>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</ContentPage.Content>
Can someone point me in the right direction for what I am trying to achieve?
In .net forms it is such a simple task, and would take me minutes to do, but this has me beaten.
Here you have considered two things,
The first one, for listview, you have to use ItemsSource property instead of BindableLayout.ItemsSource.
The second one is the BindingContext of the template will be a single item of the bindable layout source. For example, in your case CardData. So the source, your trying to binding to the ListView is not a part of CardData. So when you bind different objects inside the data template, you have bound with BindingContext keyword like BindingContext.YourProperty with source reference. Refer to the below code,
<StackLayout x:Name="baseLayout" Orientation="Horizontal" BackgroundColor="#EBEBEB" HeightRequest="130"
BindableLayout.ItemsSource="{Binding cardDatas}" WidthRequest="410">
<BindableLayout.ItemTemplate>
<DataTemplate>
<StackLayout HeightRequest="300" VerticalOptions="Start" Orientation="Vertical">
<Frame CornerRadius="0"
HorizontalOptions="Start"
VerticalOptions="Start"
Margin="0"
Padding="0"
WidthRequest="410"
HeightRequest="80"
BackgroundColor="Red"
HasShadow="true">
<StackLayout Orientation="Vertical">
<Label Text="{Binding BindingContext.bUser.FirstName, Source={x:Reference baseLayout}}"/>
<Label Text="{Binding BindingContext.bUser.LastName, Source={x:Reference baseLayout}}"/>
</StackLayout>
</Frame>
<StackLayout Orientation="Vertical" BackgroundColor="Blue">
<ListView ItemsSource="{Binding BindingContext.cardDatas, Source={x:Reference baseLayout}}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label Text ="{Binding CardName}"/>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</StackLayout>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
And the model and view model class based on your codes,
public class User
{
public int Uid { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class CardData
{
public int _id { get; set; }
public string CardName { get; set; }
public string CardNote { get; set; }
}
public class BindingUser
{
public User bUser { get; set; }
public ObservableCollection<CardData> cardDatas { get; set; }
public BindingUser()
{
cardDatas = new ObservableCollection<CardData>()
{
new CardData()
{
_id = 1,
CardName = "Testing1",
CardNote = "Test data1",
},
new CardData()
{
_id = 2,
CardName = "Testing2",
CardNote = "Test data2",
},
new CardData()
{
_id = 3,
CardName = "Testing3",
CardNote = "Test data3",
},
};
bUser = new User
{
Uid = 23432,
FirstName = "First User",
LastName = "Last User",
};
}
}
It's better use the MVVM model if you're binding complex data, the view model helps you get a clearer picture of the view and model, I made some change to the code and hope it helps:
XAML:
<StackLayout BindableLayout.ItemsSource="{Binding Data}"
Orientation="Horizontal" BackgroundColor="#EBEBEB">
<BindableLayout.ItemTemplate>
<DataTemplate>
<StackLayout>
<Frame CornerRadius="0"
HorizontalOptions="Start"
VerticalOptions="Start"
Margin="0"
Padding="0"
WidthRequest="410"
BackgroundColor="Red"
HasShadow="true">
<StackLayout Orientation="Vertical">
<Label Text="{Binding FirstName}"/>
<Label Text="{Binding LastName}"/>
</StackLayout>
</Frame>
<ListView ItemsSource="{Binding cardDatas}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label Text ="{Binding CardName}"/>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
set BindingContext in MainPage:
public partial class MainPage : ContentPage
{
DemoViewModel viewModel = new DemoViewModel();
public MainPage()
{
InitializeComponent();
this.BindingContext = viewModel;
}
}
DemoViewModel:
class DemoViewModel
{
public ObservableCollection<BindingUser> Data { get; set; }
public DemoViewModel() {
Data = new ObservableCollection<BindingUser>
{
new BindingUser(1, "aa"),
new BindingUser(2, "bb"),
new BindingUser(3, "cc"),
new BindingUser(4, "dd")
};
}
}
Class User is deleted, CardData remains the same, also you can add it back if needed.
BindingUser:
class BindingUser
{
public int Uid { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public ObservableCollection<CardData> cardDatas { get; set; }
public BindingUser(int uid, string name)
{
Uid = uid;
FirstName = name;
LastName = name;
cardDatas = new ObservableCollection<CardData>()
{
new CardData()
{
_id = 1,
CardName = "card 1",
},
new CardData()
{
_id = 2,
CardName = "card 2",
},
new CardData()
{
_id = 3,
CardName = "card 3",
},
};
}
}

Xamarin Forms - How to get the json string in POST method response?

I created a listview where it displays all categories based on the data from an API "cat_code", and if you tapped any of the it will transfer the value of the "cat_code" into a variable "selectedItem"
MenuCategories.xaml
<ListView x:Name="MyCategory" ItemSelected="MyCategory_ItemSelected" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell >
<StackLayout Orientation="Horizontal" HorizontalOptions="Center" VerticalOptions="Center" >
<Label Font="30" HorizontalTextAlignment="Center" x:Name="categoryname" Text="{Binding cat_code}"
Style="{DynamicResource ListItemTextStyle}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
MenuCategories.xaml.cs
private string selectedItem;
public MenuCategories()
{
InitializeComponent();
GetCategoryAsync();
}
public async Task GetCategoryAsync()
{
HttpClient client = new HttpClient();
var response = await client.GetStringAsync("http://ropenrom24-001-site1.etempurl.com/potangina/final/Restserver/index.php/category/view");
var cat = JsonConvert.DeserializeObject<List<Catergory>>(response);
MyCategory.ItemsSource = cat;
}
private void MyCategory_ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
var selectedCategory = e.SelectedItem as Catergory;
if (selectedCategory != null)
selectedItem = selectedCategory.cat_code;
DisplayAlert("Test", "Selected: " + selectedItem, "OK");
Catergory cat = new Catergory();
{
cat.cat_code = selectedItem;
}
var json = JsonConvert.SerializeObject(cat);
var content = new StringContent(json, Encoding.UTF8, "application/json");
HttpClient client = new HttpClient();
var result = await client.PostAsync("http://ropenrom24-001-site1.etempurl.com/potangina/final/Restserver/index.php/Products/view_cat", content);
}
If I post a cat_code:Asian it will display all of cat_code that has cat_code:Asian what I want to happen is how to get the underlined in this picture?
and transfer it to a viewmodel where i can display it to this listview?
MenuView.xaml
<ListView x:Name="ViewMenu">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<Image Source="{Binding menu_image ,StringFormat='https://i.imgur.com/{0:F0}.png'}" Scale="1" />
<Label Text="{Binding menu_name}" Font="30"/>
<Label Text="{Binding menu_price,StringFormat=''}"/>
<Label Text="{Binding menu_availability} "/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Menus.cs
public class Menus
{
public string menu_code { get; set; }
public string cat_code { get; set; }
public string menu_name { get; set; }
public string menu_price { get; set; }
public string menu_description { get; set; }
public string menu_image { get; set; }
public string menu_inventory { get; set; }
public string menu_availability { get; set; }
}
Basically my question is how to get the json string underlined in the picture above?
try this.
string json_response = await result.Content.ReadAsStringAsync();
the json_response should contain the data you need.

Xamarin Forms Picker Binding

I'd like to implement a simple picker XAML binded to 3 labels, where when I choose a value from the picker the labels will be populated automatically (the data comes from SQLite).
Here is what I have:
<Picker x:Name="ListJobs" Title="Select Job" ItemsSource="{Binding options}" ItemDisplayBinding="{Binding JobNo}" SelectedItem="{Binding SelectedJobs}"/>
<Label Text="{Binding JobsId}" IsVisible="True" x:Name="TxtId"/>
<Label Text="{Binding name}" IsVisible="True" x:Name="TxtName"/>
<Label Text="{Binding location}" IsVisible="True" x:Name="TxtLoc"/>
Model
public class Jobs
{
public string JobsId {get;set;}
public string name {get;set;}
public string location {get;set;}
public Jobs(){}
}
Code Behind:
protected override OnAppearing()
{
jobsInfo = (List<Jobs>) GetJob();
foreach (var item in jobsInfo)
{
Jobs options = new Jobs
{
JobsId = item.JobsId,
name = item.name,
location = item.location
};
BindingContext = options;
}
}
private IEnumerable<Jobs> GetJobsInfo()
{
var db = _connection.Table<Jobs>();
return db.ToList();
}
I would to select from picker (like dropdown) and populate the labels.
First, there are some mistakes in your code.
1.When you go through the loop (the data you gained from db), options is always updated with new data(so it generates using last object), and you set it to BindingContext. You should set a modelView here rather a model.
2.The itemSource of Picker must be a list, however you set a model here.
3.The viewmodel must implement INotifyPropertyChanged to notify the changes.
I think what you need understanding most is not this Picker , it is How to work with binding.
Bindable Properties
Data Binding Basics
From Data Bindings to MVVM
Okay, let us come back to this case. What you need is here
I simplified the demo and you can refer to it.
XAML
<Picker x:Name="picker"
Title="Select Job"
ItemsSource="{Binding JobList}"
ItemDisplayBinding="{Binding Name}"
SelectedItem="{Binding SelectedJob}"/>
<Label Text="{Binding SelectedJob.JobsId}" IsVisible="True" x:Name="TxtId" Margin="0,100,0,0"/>
<Label Text="{Binding SelectedJob.Name}" IsVisible="True" x:Name="TxtName"/>
<Label Text="{Binding SelectedJob.Location}" IsVisible="True" x:Name="TxtLoc"/>
Model and ViewModel:
public class Jobs
{
public string JobsId { get; set; }
public string Name { get; set; }
public string Location { get; set; }
}
public class RootModel : INotifyPropertyChanged
{
List<Jobs> jobList;
public List<Jobs> JobList
{
get { return jobList; }
set
{
if (jobList != value)
{
jobList = value;
OnPropertyChanged();
}
}
}
Jobs selectedJob;
public Jobs SelectedJob
{
get { return selectedJob; }
set
{
if (selectedJob != value)
{
selectedJob = value;
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Code behind:
public MainPage()
{
InitializeComponent();
this.BindingContext = new RootModel
{
JobList = GetJobsInfo()
};
}
private List<Jobs> GetJobsInfo()
{
var db = _connection.Table<Jobs>();
return db.ToList();
}
My Test:
XAML:
<Picker x:Name="ListJobs" Title="Select Job" ItemsSource="{Binding AllJobs}"
ItemDisplayBinding="{Binding Name}" SelectedItem="{Binding SelectedJob}"/>
<Label Text="{Binding SelectedJob.JobId}" IsVisible="True" x:Name="TxtId"/>
<Label Text="{Binding SelectedJob.Name}" IsVisible="True" x:Name="TxtName"/>
<Label Text="{Binding SelectedJob.Location}" IsVisible="True" x:Name="TxtLoc"/>
Model:
public class Job
{
public string JobId { get; set; }
public string Name { get; set; }
public string Location {get; set; }
}
public class JobModel
{
public List<Job> AllJobs { get; set; }
public Job SelectedJob { get; set; }
}
Code behind:
protected override OnAppearing()
{
BindingContext = new JobsModel {
AllJobs = GetJobs()
};
}
private List<Jobs> GetJobs()
{
var db = _connection.Table<Jobs>();
return db.ToList();
}
//How to add picker or dropdownlist in Xamarin forms and bind text ?
//we will be using Picker Properties -> pickername.ItemsSource and pickername.SelectedItem
//In above line pickername is the x:Name given to picker
//page.xaml
<Frame CornerRadius="5" HeightRequest="50" Padding="0">
<StackLayout Orientation="Horizontal">
<controls:BorderlessPicker
x:Name="Pickdoctype"
ItemDisplayBinding="{Binding text}"
SelectedIndexChanged="Pickdoctype_SelectedIndexChanged"
HorizontalOptions="FillAndExpand"
Title="Enter Document Type"
FontSize="20"
TextColor="Gray">
</controls:BorderlessPicker>
<ImageButton BackgroundColor="Transparent" Padding="0">
<ImageButton.Source>
<FontImageSource Glyph="" Size="25"
FontFamily="{StaticResource FontAwesomeSolid}"
Color="Gray"></FontImageSource>
</ImageButton.Source>
</ImageButton>
</StackLayout>
</Frame>
//page.xaml.cs
//Picker Get API
var responseUserData = await httpService.Get("manageDocument/documentType/documentType/" + UserID);
if (responseUserData.IsSuccessStatusCode)
{
var responseUserDataString = await responseUserData.Content.ReadAsStringAsync();
var myDeserializedClass = JsonConvert.DeserializeObject<List<DocumentTypeModel>>(responseUserDataString);
Pickdoctype.ItemsSource = myDeserializedClass;
}
//Get Picker value functionality
private void Pickdoctype_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
DocumentTypeModel selectedItem = (DocumentTypeModel)Pickdoctype.SelectedItem;
string PickerValue = selectedItem.value;
string PickerText = selectedItem.text;
}
catch (Exception ex)
{
}
}
//Create a model class
public class DocumentTypeModel
{
public string masterName { get; set; }
public string text { get; set; }
public string value { get; set; }
}

Categories

Resources