Count selected checkboxes in collectionview xamarin - c#

I have a collection view with a checkbox. I want to count the amount of checkboxes which have been selected and show that value in a label (string Sel). I think I have mostly done it however the label doesn't update. I think this is due to not calling OnProperty changed in the correct place which would update the label. I'm still rapping my head round MVVM. Thanks
ModelView:
public class MeetAWalkerViewModel : INotifyPropertyChanged
{
public ObservableCollection<PetProfile> source;
public ObservableCollection<PetProfile> PetInfo { get; private set; }
public ObservableCollection<PetProfile> EmptyPetInfo
{
get => source;
private set
{
if (value != source)
{
source = value;
OnPropertyChanged(nameof(EmptyPetInfo));
}
}
}
public string Sel { get; private set; }
public MeetAWalkerViewModel()
{
var count = EmptyPetInfo.Count(t => t.Selected);
Sel = "Amount of selected pets" + Convert.ToString(count);
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
Xaml:
<CollectionView x:Name="petCollectionView" ItemsSource="{Binding EmptyPetInfo}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="10" RowDefinitions="80" ColumnDefinitions="120,60,60">
<Image Grid.Column="0"
Grid.Row="0"
x:Name="PetImage"
Source="{Binding imageUrl}"/>
<Label Grid.Column="1"
Grid.Row="0"
Text="{Binding PetName}"
FontAttributes="Bold"
x:Name="labelpetname" VerticalTextAlignment="Center" HorizontalTextAlignment="Center"/>
<CheckBox Grid.Row="0" Grid.Column="2" HorizontalOptions="End" IsChecked="{Binding Selected, Mode=TwoWay}" CheckedChanged="CheckBox_CheckedChanged" BindingContext="{Binding .}"/>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>

I made a sample based on your code, it works properly.
You can refer to the following code:
MeetAWalkerViewModel.cs
public class MeetAWalkerViewModel: INotifyPropertyChanged
{
public ObservableCollection<PetProfile> source;
//public ObservableCollection<PetProfile> PetInfo { get; private set; }
public ObservableCollection<PetProfile> EmptyPetInfo
{
get => source;
private set
{
if (value != source)
{
source = value;
OnPropertyChanged(nameof(EmptyPetInfo));
}
}
}
int _count;
public int Count
{
set
{
if (_count != value)
{
_count = value;
OnPropertyChanged(nameof(Count));
Sel = "Amount of selected pets is : " + Convert.ToString(_count);
}
}
get
{
return _count;
}
}
public void updateCount(int count) {
}
String sel;
public String Sel
{
set
{
if (sel != value)
{
sel = value;
OnPropertyChanged(nameof(Sel));
}
}
get
{
return sel;
}
}
public MeetAWalkerViewModel()
{
EmptyPetInfo = new ObservableCollection<PetProfile>();
EmptyPetInfo.Add(new PetProfile { PetName = "Pet1", IsSelected= false,ImageUrl= "cherry.png" });
EmptyPetInfo.Add(new PetProfile { PetName = "Pet2", IsSelected = false, ImageUrl = "watermelon.png" });
EmptyPetInfo.Add(new PetProfile { PetName = "Pet3", IsSelected = false, ImageUrl = "cherry.png" });
EmptyPetInfo.Add(new PetProfile { PetName = "Pet4", IsSelected = false, ImageUrl = "watermelon.png" });
EmptyPetInfo.Add(new PetProfile { PetName = "Pet5", IsSelected = false, ImageUrl = "cherry.png" });
EmptyPetInfo.Add(new PetProfile { PetName = "Pet6", IsSelected = false, ImageUrl = "watermelon.png" });
foreach (PetProfile petProfile in EmptyPetInfo) {
if (petProfile.IsSelected)
{
Count++;
}
}
Sel = "Amount of selected pets is : " + Convert.ToString(Count);
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
MainPage.xaml
<StackLayout HorizontalOptions="Center" Padding="10" >
<Label x:Name="countSelectedItemsLabel" Text="{Binding Sel}" FontSize="20" />
<CollectionView x:Name="petCollectionView" ItemsSource="{Binding EmptyPetInfo}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="10" RowDefinitions="80" ColumnDefinitions="120,60,60">
<Image Grid.Column="0"
Grid.Row="0"
x:Name="PetImage"
Source="{Binding ImageUrl}"/>
<Label Grid.Column="1"
Grid.Row="0"
Text="{Binding PetName}"
FontAttributes="Bold"
x:Name="labelpetname" VerticalTextAlignment="Center" HorizontalTextAlignment="Center"/>
<CheckBox Grid.Row="0" Grid.Column="2" HorizontalOptions="End" IsChecked="{Binding IsSelected, Mode=TwoWay}" CheckedChanged="CheckBox_CheckedChanged" BindingContext="{Binding .}"/>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
MainPage.xaml.cs
public partial class MainPage : ContentPage
{
MeetAWalkerViewModel viewModel;
int selectedCount = 0;
public MainPage()
{
InitializeComponent();
viewModel = new MeetAWalkerViewModel();
BindingContext = viewModel;
}
private void CheckBox_CheckedChanged(object sender, CheckedChangedEventArgs e)
{
PetProfile model = (PetProfile)((CheckBox)sender).BindingContext;
if (model.IsSelected)
{
selectedCount++;
}
else
{
selectedCount--;
}
viewModel.Count = selectedCount;
}
}
PetProfile.cs
public class PetProfile
{
public string PetName { get; set; }
public string ImageUrl { get; set; }
public bool IsSelected { get; set; }
}
The result is:

You need to change the String like this
String sel ;
public String Sel
{
set
{
if (sel != value)
{
sel = value;
OnPropertyChanged(nameof(Sel ));
}
}
get
{
return sel ;
}
}

Related

Trying to set picker within listview MVVM Xamarin

Trying to set the initial value to a picker through the use of SelectedItem. I can do this without any issue if the picker isn't within a listview. However, once I try to accomplish this in a listview no dice.
I never can get the picker to display the initially downloaded value. If I use the same binding for an entry it displays the expected string.
Thoughts??
This can be reproduced in this simplistic standalone project. Please help. Thanks.
https://github.com/smarcus3/DebuggingProject
XAML
<ListView x:Name="listView" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" ItemsSource="{Binding downloadedRecipeIngredients}"> <!--SelectedItem="{Binding SelectedItem}"-->
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<!-- Element Label -->
<Entry VerticalOptions="CenterAndExpand" HorizontalOptions="StartAndExpand" Text="{Binding IngredientName}"/>
<!--<Picker x:Name="pickerIngredient" HorizontalOptions = "StartAndExpand" ItemsSource="{Binding listIngredients}" BindingContext="{Binding Source={x:Reference Page}, Path=BindingContext}" SelectedItem="{Binding IngredientName}" WidthRequest="100"/>-->
<Picker x:Name="pickerIngredientancestor" HorizontalOptions = "StartAndExpand" WidthRequest="100" ItemsSource="{Binding listIngredients, Source={RelativeSource AncestorType={x:Type viewModel:testPageViewModel}}}" SelectedItem="{Binding IngredientName}"/>
<Entry Text="{Binding Quantity}" VerticalOptions="CenterAndExpand" HorizontalOptions="StartAndExpand" />
<Entry Text="{Binding UnitName}" VerticalOptions="CenterAndExpand" HorizontalOptions="StartAndExpand" />
<Entry Text="{Binding Comments}" VerticalOptions="CenterAndExpand" HorizontalOptions="StartAndExpand" />
<!-- Assessment Menu Icon -->
<Label Text="Clickable Label" VerticalOptions="CenterAndExpand" HorizontalOptions="EndAndExpand">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Path=BindingContext.btnPress, Source={x:Reference Page}}" CommandParameter="{Binding .}" />
</Label.GestureRecognizers>
</Label>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
VIEW MODEL
public class testPageViewModel : BaseViewModel
{
clRecipeIngredient[] _downloadedRecipeIngredients;
public clRecipeIngredient[] downloadedRecipeIngredients
{
get {
return _downloadedRecipeIngredients;
}
set
{
//if (downloadedRecipeIngredients != value)
//{
_downloadedRecipeIngredients = value;
OnPropertyChanged("downloadedRecipeIngredients");
//}
}
}
//Lists for Pickers
ObservableCollection<string> _listIngredients = new ObservableCollection<string>();
public ObservableCollection<string> listIngredients { get { return _listIngredients; } }
private clRecipeDataBase recipeDataBase;
public testPageViewModel()
{
recipeDataBase = new clRecipeDataBase();
btnPress = new Command<clRecipeIngredient>(madeIt);
getData();
}
async void getData()
{
//PICKER INGREDIENT DATA
clIngredient[] tmp = await recipeDataBase.getIngredientData();
for (int i = 0; i < tmp.Length; i++)
{
_listIngredients.Add(tmp[i].IngredientName);
}
_downloadedRecipeIngredients = await recipeDataBase.getRecipeIngredientsDataByRecipeID(310); //HARDCODED TO CRISPY PIZZA RECIPE
OnPropertyChanged("downloadedRecipeIngredients");
}
public ICommand btnPress { get; private set; }
void madeIt(clRecipeIngredient x)
{
Console.WriteLine(x.IngredientName + " -- " + x.Comments);
//_downloadedRecipeIngredients.Remove(x);
}
}
clRecipeIngredients
public class clRecipeIngredient
{
public int RecipeIngredientsID { get; set; }
public int RecipeIDLookedUP { get; set; }
public int IngredientIDLookedUp { get; set; }
public double Quantity { get; set; }
public int UnitIDLookedUp { get; set; }
public bool HiddenFlag { get; set; }
public string UnitName { get; set; }
public string IngredientName { get; set; }
public string Comments { get; set; }
I checked your sample and you could modify it like following .
in Xaml
<Picker HorizontalOptions = "StartAndExpand" WidthRequest="100" ItemsSource="{Binding Path=BindingContext.listIngredients, Source={x:Reference Page}}" SelectedItem="{Binding IngredientName, Mode=TwoWay}" />
in ViewModel
ObservableCollection had implemented the interface INotifyPropertyChanged in default . So you could simplify the code in your ViewModel .
Note : You could not set the value of SelectItem as a string directly even if they are equal . You need to set it like following
ing.IngredientName = listIngredients[0];
So the ViewModel could like
public class testPageViewModel : BaseViewModel
{
public ObservableCollection<clRecipeIngredient> downloadedRecipeIngredients
{
get;set;
}
public ObservableCollection<string> listIngredients { get; set; }
//private clRecipeDataBase recipeDataBase;
public testPageViewModel()
{
//recipeDataBase = new clRecipeDataBase();
btnPress = new Command<clRecipeIngredient>(madeIt);
downloadedRecipeIngredients = new ObservableCollection<clRecipeIngredient>();
listIngredients = new ObservableCollection<string>();
getData();
}
async void getData()
{
//PICKER INGREDIENT DATA
//clIngredient[] arrayIngredients = await recipeDataBase.getIngredientData();
//clIngredient[] arrayIngredients = new clIngredient[5];
//arrayIngredients[0].IngredientName = "Apple";
//arrayIngredients[1].IngredientName = "Salt";
//arrayIngredients[2].IngredientName = "Buuter";
//arrayIngredients[3].IngredientName = "Flour";
//arrayIngredients[4].IngredientName = "Egg";
listIngredients.Add("Apple");
listIngredients.Add("Salt");
listIngredients.Add("Butter");
listIngredients.Add("Flour");
listIngredients.Add("Egg");
//for (int i = 0; i < arrayIngredients.Length; i++)
//{
// _listIngredients.Add(arrayIngredients[i].IngredientName);
//}
//clRecipeIngredient[] arryRecipeIngredients = await recipeDataBase.getRecipeIngredientsDataByRecipeID(310); //HARDCODED TO CRISPY PIZZA RECIPE
clRecipeIngredient ing = new clRecipeIngredient();
ing.IngredientName = listIngredients[0];
ing.Quantity = 1;
ing.UnitName = "Cups";
ing.Comments = "Comments0";
clRecipeIngredient ing2 = new clRecipeIngredient();
ing2.IngredientName = listIngredients[1];
ing2.Quantity = 2;
ing2.UnitName = "Whole";
ing2.Comments = "Comments1";
downloadedRecipeIngredients.Add(ing);
downloadedRecipeIngredients.Add(ing2);
}
public ICommand btnPress { get; private set; }
void madeIt(clRecipeIngredient x)
{
Console.WriteLine(x.IngredientName + " -- " + x.Comments);
//_downloadedRecipeIngredients.Remove(x);
}
}
And don't forget to implement INotifyPropertyChanged in your model as the value of IngredientName will been changed .
public class clRecipeIngredient : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(
[CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this,new PropertyChangedEventArgs(propertyName));
}
//...
string ingredientName;
public string IngredientName
{
get
{
return ingredientName;
}
set
{
if (ingredientName != value)
{
ingredientName = value;
OnPropertyChanged("IngredientName");
}
}
}
//...
}
Its still unclear why you cannot directly set the selectedItem with a string as I can do in pickers not inside of a ListView.
However, setting the picker to use the SelectedIndex property works great. This is the KEY. For ListView's containing pickers I will not set their value based on INDEX instead of SelectedItem.
Final Code Snippets
XAML
<Picker HorizontalOptions = "StartAndExpand" WidthRequest="100" ItemsSource="{Binding Path=BindingContext.listIngredients, Source={x:Reference Page}}" SelectedIndex="{Binding IngredientIDLookedUp}" />
View Model
clRecipeIngredient[] arryRecipeIngredients = await recipeDataBase.getRecipeIngredientsDataByRecipeID(310); //HARDCODED TO CRISPY PIZZA RECIPE
clRecipeIngredient ing = new clRecipeIngredient();
_downloadedRecipeIngredients.Clear();
for (int i = 0;i < arryRecipeIngredients.Length;i++)
{
for (int j=0; j<_listIngredients.Count;j++)
{
//FIND THE SELECTED INDEX BASED ON PICKER’S LIST and STORE IN THE CUSTOM CLASS
if(arryRecipeIngredients[i].IngredientName == _listIngredients[j])
{
arryRecipeIngredients[i].IngredientIDLookedUp = j;
}
}
_downloadedRecipeIngredients.Add(arryRecipeIngredients[i]);
}

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; }
}

Xamarin.Forms Add and Share Item CrashApp

Good morning to all, I've looked in several places I researched and did not found a solution that worked for my problems.
I'm new to C #, XAML and Xamarin, I am doing an application that creates lists with products on a screen, the screen with products is been populated via Json WebApi. Until there everthing looks fine, but since i tried to add 'ADD' and 'Share' functionalities it is loading the main page and crashes on navigating to listsPage.
I need to get a product from the product Page and add it to another view where my lists are. I created a ContextActions with 'Share' and 'AddToList' but i don't know how to get that product and 'Add' it to my lists. Same problem with 'Share' when i get the MenuItem and try to pass it to a Task in my ProductViewModel i get a NullReferenceException, but the object is not null.
I appreciate if someone could help me with this issues.
I know the post has got quite long but i wanted to give every possible info.
Here is my Lists Page:
<ListView x:Name="listaView" ItemSelected="listSelected" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout Padding="20,0,20,0"
Orientation="Horizontal"
HorizontalOptions="FillAndExpand">
<Label Text="{Binding Name}"
VerticalTextAlignment="Center"
HorizontalOptions="StartAndExpand" />
<Image Source="check.png"
HorizontalOptions="Start"
IsVisible="{Binding Done}" />
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
and my listDetail:
<Label Text="Name" />
<Entry x:Name="nameEntry" Text="{Binding Name}" />
<Label Text="Description" />
<Entry x:Name="descriptionEntry" Text="{Binding Description}" />
<Label Text="Typ" />
<controls:BindablePicker x:TypeArguments="enums:Typ" SelectedItem="{Binding Typ}" />
<Label Text="Done" />
<Switch x:Name="doneEntry" IsToggled="{Binding Done}" />
<Label Text="Products:" />
<ListView ItemsSource="{Binding Products}" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout Orientation="Horizontal">
<Image Aspect="AspectFit" HeightRequest="20" WidthRequest="20" Source="{Binding Image}" />
<Label Text="{Binding Name}" />
<Label Text="{Binding Price, StringFormat='R${0:C2}'}" />
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button Text="Save" Clicked="salveClicked" />
<Button Text="Delete" Clicked="deleteClicked" />
<Button Text="Cancel" Clicked="cancelClicked" />
<Button Text="Speak" Clicked="speakClicked" />
</StackLayout>
</ContentPage>
ListDetails CODE BEHIND:
public ProductListDetailPage()
{
InitializeComponent();
NavigationPage.SetHasNavigationBar(this, true);
}
void saveClicked(object sender, EventArgs e)
{
var lista = (Lists)BindingContext;
App.Database.SaveList(lista);
this.Navigation.PopAsync();
}
void deleteClicked(object sender, EventArgs e)
{
var lista = (Lists)BindingContext;
App.Database.DeleteList(lista.ListaID);
this.Navigation.PopAsync();
}
void cancelClicked(object sender, EventArgs e)
{
var lista = (Lists)BindingContext;
this.Navigation.PopAsync();
}
void speakClicked(object sender, EventArgs e)
{
var lists = (Lists)BindingContext;
DependencyService.Get<ITextToSpeech>().Speak(lists.Name+ " " + lists.Descrip);
}
}
}
I believe the problem is in my model but have no idea what it is
Product Model:
public class Product : INotifyPropertyChanged
{
private int id;
public int ProductID
{
get { return id; }
set
{
id = value;
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(id)));
}
}
private string name;
public string Name
{
get { return name; }
set
{
name= value;
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(name)));
}
}
private double price;
public double Price{
get { return price; }
set
{
price= value;
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(price)));
}
}
private string dtFab;
public string DtFab
{
get { return dtFab; }
set
{
dtFab= value;
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(dtFab)));
}
}
private string dtValid;
public string DtValid {
get { return dtValid; }
set
{
dtValid= value;
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(dtValid)));
}
}
private string amount;
public string Amount{
get { return quantidade; }
set
{
amount= value;
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(amount)));
}
}
private string descrip;
public string Descrip{
get { return descrip; }
set
{
descrip= value;
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(descrip)));
}
}
private string image;
public string Image
{
get { return image; }
set
{
image= value;
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(image)));
}
}
private ICollection<ListProduct> listProduct;
public ICollection<ListProduct> ListProduct{
get { return listProduct; }
set
{
listProduct= value;
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(listProduct)));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
ListsModel:
public class Lists
{
public Lista()
{
}
[PrimaryKey, AutoIncrement]
public int ListID get; set; }
public string Name { get; set; }
public string Descrip { get; set; }
public bool Done { get; set; }
public Typ Typ { get; set; }
public virtual ICollection<ListsProduct> ListsProducts{ get; set; }
}
public class ListsProduct
{
public int ListsProductID{ get; set; }
public int ListID { get; set; }
public int ProductID { get; set; }
public virtual Lists Lists { get; set; }
public virtual Product Product { get; set; }
}
}
ListProductModel:
SearchProductPage:
<StackLayout Orientation="Vertical">
<SearchBar Text="{Binding SearchBarText}" />
<Button x:Name="btnPesquisar" Text="Search" Command="{Binding SearchCommand}" />
<ListView ItemsSource="{Binding Products}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.ContextActions>
<MenuItem Text="Share" Clicked="ShareProduct" />
<MenuItem Text="Add To" Clicked="AddProduct" />
</ViewCell.ContextActions>
<ViewCell.View>
<StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand" >
<Image Aspect="AspectFit" HeightRequest="20" WidthRequest="20" Source="{Binding Image}" />
<Label Text="{Binding Name}" />
<Label Text="{Binding Price, StringFormat='R${0:C2}'}" HorizontalOptions="End" />
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
SearchPage CODE BEHIND:
public partial class SearchPage: ContentPage
{
ProductsViewModel viewModel;
public TelaPesquisaView()
{
InitializeComponent();
this.BindingContext = new ViewModels.ProductsViewModel();
}
public async void AddProduct(object sender, EventArgs e)
{
var al = ((MenuItem)sender);
await viewModel.AddToList(al.BindingContext as Product);
var produtoLista = new ListsPage();
await Navigation.PushAsync(produtoLista);
}
public async void ShareProduct(object sender, EventArgs e)
{
var al = ((MenuItem)sender);
if (al != null) {
await viewModel.Share(al.BindingContext as Produto);
}
}
}
}
And the ProductViewModel
public class ProductViewModel : INotifyPropertyChanged
{
private string searchBarText = string.Empty;
public string SearchBarText {
get { return searchBarText ; }
set
{
if (searchBarText != value)
{
searchBarText = value ?? string.Empty;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(searchBarText )));
if (SearchCommand.CanExecute(null))
{
SearchCommand.Execute(null);
}
}
}
}
// filtrar somente os 5 primeiros
#region Command SearchCommand
private Xamarin.Forms.Command searchCommand;
public ICommand SearchCommand{
get
{
searchCommand= searchCommand?? new Xamarin.Forms.Command(DoSearchCommand, ExecuteCommand);
return searchCommand;
}
set
{
searchCommand= (Xamarin.Forms.Command)value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(searchCommand)));
}
}
private void DoSearchCommand()
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Products)));
}
private bool ExecuteCommand()
{
return true;
}
#endregion
private ObservableCollection<Models.Produto> products;
public ObservableCollection<Models.Produto> Products {
get
{
ObservableCollection<Models.Product> searchProducts = new ObservableCollection<Models.Product>();
if (products != null)
{
List<Models.Product> prod = (from p in products
where p.Name.ToLower().Contains(searchBarText.ToLower())select p).Take(3).ToList<Models.Product>();
if (prod != null && prod.Any())
{
searchedProducts = new ObservableCollection<Models.Product>(prod);
}
}
return searchedProducts ;
}
set
{
products = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Products)));
}
}
public ProductsViewModel()
{
SearchCommand = new Xamarin.Forms.Command(async () =>
{
var products = await ApiProducts.Api.GetAsync();
Products = new ObservableCollection<Models.Product>(products );
});
}
public async Task AddToList(ListsProduct prod)
{
Lists list = new Lists();
list.ListsProduct.Add(prod);
App.Database.SaveList(list);
}
public async Task Share(Models.Product prod)
{
var title = prod.NomeProduto;
var message = prod.ToString();
// Share message and an optional title.
await CrossShare.Current.Share(message, title );
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
Here is the starting point for you. For the rest you can use the same pattern passing your new product in constructors or just implement setters in your view models.
Define binding to get a new product
<MenuItem Text="Adicionar à" Clicked="AdicionaProduto" CommandParameter="{Binding .}" />
Then pass it to your ListasView constructor as parameter
public async void AdicionaProduto(object sender, EventArgs e)
{
var al = ((MenuItem)sender);
var produtoLista = new ListasView(al.CommandParameter as Produto);
await Navigation.PushAsync(produtoLista);
}
To be able to do that you need to change a constructor
public ListasView(Produto newProduto = null)
{
InitializeComponent();
//this.BindingContext = new ViewModels.ListasViewModel();
if (newProduto != null)
{
//do something
int x = 0;
}
You can take that newProduto and store it in your DB or pass further to other models or views via constructor or some setters.

Xaml Windows phone 8

I would like to show 6 values from the database in my corresponding page horizontally as for example
Date|Time|Floor|Zone|Latitude|longitude
But the page only shows
Data|Time|Floor|Zone
and does not show the latitude and longitude
Below is my Xaml code
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
<StackPanel Grid.Row="0" Margin="12,17,0,28">
<TextBlock Text="Smart Parking" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock Text="History" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ListBox x:Name="ListData">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock x:Name= "DateTxt" Text="{Binding Date}" TextWrapping="Wrap" />
<TextBlock x:Name= "TimeTxt" Text="{Binding Time}" TextWrapping="Wrap" />
<TextBlock x:Name= "ZoneTxt" Text="{Binding Zone}" TextWrapping="Wrap"/>
<TextBlock x:Name= "FloorTxt" Text="{Binding Floor}" TextWrapping="Wrap"/>
<TextBlock x:Name= "LatTxt" Text="{Binding location_latitude}" TextWrapping="Wrap" />
<TextBlock x:Name= "LongTxt" Text="{Binding location_longitude}" TextWrapping="Wrap" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Grid>
Can anyone please help me improve it or correct it ?
The code behind for list itmesource is here below
public partial class History : PhoneApplicationPage
{
// string dbPath = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "db.sqlite");
ObservableCollection<historyTableSQlite> DB_HistoryList = new ObservableCollection<historyTableSQlite>();
DbHelper add = new DbHelper();
public History()
{
InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
add.AddInfo();
ReadHistoryList_Loaded();
}
public void ReadHistoryList_Loaded()
{
ReadAllContactsList dbhistory = new ReadAllContactsList();
DB_HistoryList = dbhistory.GetAllHistory();//Get all DB contacts
ListData.ItemsSource = DB_HistoryList.OrderByDescending(i => i.Id).ToList();//Latest contact ID can Display first
}
here below is DBhelper class for all the main functions
public class DbHelper
{
SQLiteConnection dbConn;
public async Task<bool> onCreate(string DB_PATH)
{
try
{
if (!CheckFileExists(DB_PATH).Result)
{
using (dbConn = new SQLiteConnection(DB_PATH))
{
dbConn.CreateTable<historyTableSQlite>();
}
}
return true;
}
catch
{
return false;
}
}
private async Task<bool> CheckFileExists(string fileName)
{
try
{
var store = await Windows.Storage.ApplicationData.Current.LocalFolder.GetFileAsync(fileName);
return true;
}
catch
{
return false;
}
}
//retrieve all list from the database
public ObservableCollection<historyTableSQlite> ReadHistory()
{
using (var dbConn = new SQLiteConnection(App.DB_PATH))
{
List<historyTableSQlite> myCollection = dbConn.Table<historyTableSQlite>().ToList<historyTableSQlite>();
ObservableCollection<historyTableSQlite> HistoryList = new ObservableCollection<historyTableSQlite>(myCollection);
return HistoryList;
}
}
// Insert the new info in the histrorytablesqlite table.
public void Insert(historyTableSQlite newcontact)
{
using (var dbConn = new SQLiteConnection(App.DB_PATH))
{
dbConn.RunInTransaction(() =>
{
dbConn.Insert(newcontact);
});
}
}
public void AddInfo()
{
DbHelper Db_helper = new DbHelper();
Db_helper.Insert((new historyTableSQlite
{
Date = DateTime.Now.ToShortDateString(),
Time = DateTime.Now.ToShortTimeString(),
Zone = "PST",
Floor = "10th Floor",
latitude = 35.45112,
longtitude = -115.42622
}));
}
}
and the last class for keeping the values
public class historyTableSQlite : INotifyPropertyChanged
{
[SQLite.PrimaryKey, SQLite.AutoIncrement]
public int Id { get; set; }
private int idvalue;
private string dateValue = string.Empty;
public string Date {
get { return this.dateValue; }
set
{
if (value != this.dateValue)
{
this.dateValue = value;
NotifyPropertyChanged("Date");
}
}
}
private string timeValue = string.Empty;
public string Time
{
get { return this.timeValue; }
set
{
if (value != this.timeValue)
{
this.timeValue = value;
NotifyPropertyChanged("Time");
}
}
}
private string floorValue = string.Empty;
public string Floor
{
get { return this.floorValue; }
set
{
if (value != this.floorValue)
{
this.floorValue = value;
NotifyPropertyChanged("Floor");
}
}
}
public string zoneValue;
public string Zone
{
get { return this.zoneValue; }
set
{
if (value != this.zoneValue)
{
this.zoneValue = value;
NotifyPropertyChanged("Zone");
}
}
}
private double latValue;
public double latitude
{
get { return latValue; }
set
{
if (value != this.latValue)
{
this.latValue = value;
NotifyPropertyChanged("Latitude");
}
}
}
private double lonValue;
public double longtitude
{
get { return this.lonValue; }
set
{
if (value != this.lonValue)
{
this.lonValue = value;
NotifyPropertyChanged("Longitude");
}
}
}
// public string isMarkPoint { get; set; }
public historyTableSQlite()
{
}
public historyTableSQlite(string date,string time,string floor,string zone,double lat,double lng)
{
Date = date;
Time = time;
Floor = floor;
Zone = zone;
latitude = lat;
longtitude = lng;
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
You are binding your textblock to location_longitude but I don't see any location_longitude (or latitude) in your code behind.
Plus, you have a little misspelling in your Longitude and Latitude declarations
public double longtitude // Here change to Longitude
{
get { return this.lonValue; }
set
{
if (value != this.lonValue)
{
this.lonValue = value;
NotifyPropertyChanged("Longitude");
}
}
}
private double latValue;
public double latitude // Change to Latitude
{
get { return latValue; }
set
{
if (value != this.latValue)
{
this.latValue = value;
NotifyPropertyChanged("Latitude");
}
}
}
Try to bind your textblock as
<TextBlock x:Name="LatTxt" Text="{Binding Latitude}" TextWrapping="Wrap" />
<TextBlock x:Name="LongTxt" Text="{Binding Longitude}" TextWrapping="Wrap" />
Hope this help.

Cannot access a checkbox in a datatemplate [duplicate]

This question already has an answer here:
How to access a child control's property when it is declared in a ControlTemplate?
(1 answer)
Closed 2 years ago.
<GroupBox x:Name="CrashGenerationGroupBox" Header="Crash Generation" Margin="5" FontSize="18" FontWeight="SemiBold">
<GroupBox.HeaderTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox x:Name="cbHeaderCrashGeneration"/>
<TextBlock Text="{Binding}"/>
</StackPanel>
</DataTemplate>
</GroupBox.HeaderTemplate>
<StackPanel Orientation="Horizontal">
<RadioButton GroupName="CrashGeneration" Content="Oscar" IsEnabled="{Binding ElementName=cbHeaderCrashGeneration, Path=IsChecked}"/>
<RadioButton GroupName="CrashGeneration" Content="CrashSimulator" IsEnabled="{Binding ElementName=cbHeaderCrashGeneration, Path=IsChecked}"/>
</StackPanel>
</GroupBox>
I am trying to access the IsChecked property of the CheckBox defined in the header template of the GroupBox. But i see i can't access that CheckBox state. I've tried also to use in the code behind and it's not available also. Can somebody give me a hint here?
Your XAML will look like this...
<Grid>
<DataGrid x:Name="datagrid1" AutoGenerateColumns="True">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Select Value">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox Name="Chk" Tag="{Binding}" Checked="Chk_Checked"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.HeaderTemplate>
<DataTemplate>
<CheckBox Name="ChkAll" Checked="ChkAll_Checked" Unchecked="ChkAll_Unchecked" IsThreeState="False" Padding="4,3,4,3" HorizontalContentAlignment="Center" HorizontalAlignment="Center"/>
</DataTemplate>
</DataGridTemplateColumn.HeaderTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
And the code behind would be like this:
public partial class MainWindow : Window
{
private ObservableCollection<customer> custcol;
public ObservableCollection<customer> custCol
{
get { return custcol; }
set
{
custcol = value;
}
}
public MainWindow()
{
InitializeComponent();
custcol = new ObservableCollection<customer>();
custCol.Add(new customer { custID = 1, custName = "1", Status = "InActive", Flag = true });
custCol.Add(new customer { custID = 2, custName = "2", Status = "InActive", Flag = false });
custCol.Add(new customer { custID = 3, custName = "3", Status = "InActive", Flag = false });
datagrid1.ItemsSource = this.custCol;
}
private void ChkAll_Checked(object sender, RoutedEventArgs e)
{
}
private void ChkAll_Unchecked(object sender, RoutedEventArgs e)
{
}
private void Chk_Checked(object sender, RoutedEventArgs e)
{
switch (((sender as CheckBox).Tag as customer).custID)
{
case 1: break;
case 2: break;
case 3: break;
}
}
}
public class customer : INotifyPropertyChanged
{
public object obj { get; set; }
public int custID { get; set; }
private string custname;
public string custName
{
get { return custname; }
set
{
custname = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("custName"));
}
}
}
public DateTime startTime { get; set; }
public DateTime endTime { get; set; }
private string status;
public string Status
{
get { return status; }
set
{
status = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Status"));
}
}
}
private string duration;
public string Duration
{
get { return duration; }
set
{
duration = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Duration"));
}
}
}
public bool Flag { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
}

Categories

Resources