Xaml Windows phone 8 - c#

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.

Related

Count selected checkboxes in collectionview xamarin

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

How refresh view after added new item

I have problem because if I add new item in my observablecollection this i don't see result in my view.
I need a restart, then I can see the new item.
Here is my viewmodel where i dispaly items
public class ManageFleetListingViewModel : ViewModelBase
{
private readonly Func<IEnumerable<DisplayManageFleetViewModel>,IEnumerable<DisplayManageFleetViewModel>> _filtersVehicle;
private readonly ObservableCollection<DisplayManageFleetViewModel> _manageFleetViewModel;
private readonly VehicleState _vehicleState;
private readonly IManageFleetService _manageFleetService;
public IEnumerable<DisplayManageFleetViewModel> Vehicles => _manageFleetViewModel;
public ICommand DeleteVehicleCommand { get; set; }
public ManageFleetListingViewModel(VehicleState vehicleState, IManageFleetService manageFleetService) : this(vehicleState,manageFleetService, manageFleet => manageFleet) { }
public ManageFleetListingViewModel(VehicleState vehicleState, IManageFleetService manageFleetService, Func<IEnumerable<DisplayManageFleetViewModel>, IEnumerable<DisplayManageFleetViewModel>> filtersVehicle )
{
DeleteVehicleCommand = new DeleteVehicleCommand(this, manageFleetService);
_filtersVehicle = filtersVehicle;
_vehicleState = vehicleState;
_manageFleetViewModel = new ObservableCollection<DisplayManageFleetViewModel>();
_vehicleState.StateChanged += VehicleState_StateChanged;
DisplayVehicles();
}
public void DeleteItem(int id)
{
var item = Vehicles.FirstOrDefault(x => x.Id == id);
_manageFleetViewModel.Remove(item);
}
public void AddItem()
{
DisplayVehicles();
}
private void DisplayVehicles()
{
IEnumerable<DisplayManageFleetViewModel> displayManageFleets = _vehicleState.GetVehicles
.Select(s => new DisplayManageFleetViewModel(s.Id, s.CarBrand, s.VIN, s.Milage, s.EnigneNumber, s.EngineCapacity, s.RegistrationNumber, s.FirstRegistration, s.YearPurchase, s.YearProduction, s.ImageCar));
displayManageFleets = _filtersVehicle(displayManageFleets);
_manageFleetViewModel.Clear();
foreach (DisplayManageFleetViewModel viewModel in displayManageFleets)
{
_manageFleetViewModel.Add(viewModel);
}
}
private void VehicleState_StateChanged()
{
DisplayVehicles();
}
This is my project domain where I add item
public class ManageFleetService : IManageFleetService
{
private readonly IDataService<Account> _accountService;
private readonly IVehicleService _vehicleService;
public ManageFleetService(IDataService<Account> accountService, IVehicleService vehicleService)
{
_accountService = accountService;
_vehicleService = vehicleService;
}
public async Task<Account> AddVehicle(string carBrand, string vin, string milage, string engineNumber, string engineCapacity, string registerNumber, DateTime firstRegistration, DateTime yearPurchase, DateTime yearProduction, byte[] imageCar,Account accountId)
{
Vehicle vehicleVIN = await _vehicleService.GetByVIN(vin);
if(vehicleVIN != null)
{
throw new InvalidVinNumberException(vin);
}
Vehicle vehicleRegistraion = await _vehicleService.GetByRegistrationNumber(registerNumber);
if(vehicleRegistraion != null)
{
throw new InvalidRegistrationNumberException(registerNumber);
}
Vehicle vehicle = new Vehicle()
{
CarBrand = carBrand,
VIN = vin,
Milage = milage,
EnigneNumber = engineNumber,
EngineCapacity = engineCapacity,
RegistrationNumber = registerNumber,
FirstRegistration = firstRegistration,
YearPurchase = yearPurchase,
YearProduction = yearProduction,
ImageCar = imageCar,
Account = accountId
};
accountId.Vehciles = new List<Vehicle>();
accountId.Vehciles.Add(vehicle);
await _accountService.Update(accountId, accountId.Id);
return accountId;
}
When the item is added to the database i display next time functions DisplayVehicles in Command
Account account = await _manageFleetService.AddVehicle(carBrand, vin, milage, engineCapacity, engineCapacity, registerNumber, firstRegistration, yearPurchase, yearProduction, imageCar, _accountStore.CurrentAccount);
_manageFleetListingViewModel.AddItem();
This is my userconrol (ManageFleetListing) xaml where i display items
<Grid>
<StackPanel HorizontalAlignment="Center">
<ItemsControl ItemsSource="{Binding Vehicles}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Task:VehcileTask/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Grid>
Here is my pattern for VehicleTask
<StackPanel>
<Border>
</Border>
<StackPanel Orientation="Horizontal">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
</Grid>
<StackPanel Grid.Column="0" MinWidth="150" MaxWidth="300">
<TextBlock Text="{Binding CarBrand}" FontSize="12" FontWeight="DemiBold"/>
</StackPanel>
<StackPanel Grid.Column="1" MinWidth="150" MaxWidth="300">
<TextBlock Text="{Binding VIN}" FontSize="12" FontWeight="DemiBold"/>
</StackPanel>
<StackPanel Grid.Column="2" MinWidth="100" MaxWidth="200">
<TextBlock Text="{Binding Milage}" FontSize="12" FontWeight="DemiBold"/>
</StackPanel>
<StackPanel Grid.Column="3" MinWidth="100" MaxWidth="200" Margin="0 0 20 0">
<TextBlock Text="{Binding YearProduction, StringFormat='dd/MM/yyyy'}" FontSize="12" FontWeight="DemiBold"/>
</StackPanel>
<Button Content="Edit" Command="{Binding Path=DataContext.DeleteVehicleommand, RelativeSource={RelativeSource AncestorType=local:ManageFleetListing}}"/>
<Button Background="Red" BorderThickness="0" Content="Delete" Command="{Binding Path=DataContext.DeleteVehicleCommand, RelativeSource={RelativeSource AncestorType=local:ManageFleetListing}}" Margin="10 0 0 0" CommandParameter="{Binding Id}"/>
</StackPanel>
<Border BorderThickness="1" Background="Black"></Border>
</StackPanel>
This is main view here i use CreateVehicleCommandand and display ManageFleetListing
<Button
Command="{Binding CreateVehicleCommand}"
Style="{DynamicResource InventoryButton}" Height="50" Width="200" HorizontalAlignment="Left" Margin="40 20 0 0">
<Button.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF5DFF00"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</Button.Background>
<Button.Content>
<TextBlock Text="Add" FontSize="20" FontWeight="Bold" Foreground="Gray"/>
</Button.Content>
</Button>
<Grid Grid.Row="5" Height="200" Margin="0 10 0 0">
<ManageFleet:ManageFleetListing DataContext="{Binding ManageFleetListingViewModel}"/>
</Grid>
and this is view model for xaml above
public class ManageFleetViewModel : ViewModelBase
{
public ICommand CreateVehicleCommand { get; set; }
public ManageFleetListingViewModel ManageFleetListingViewModel { get; }
public ManageFleetViewModel(IManageFleetService menageFleetService, IAccountStore accountStore,VehicleState vehicleState, IManageFleetService manageFleetService,ManageFleetListingViewModel manageFleetListingViewModel)
{
CreateVehicleCommand = new CreateVehicleCommand(this, menageFleetService, accountStore, manageFleetListingViewModel);
ManageFleetListingViewModel = new ManageFleetListingViewModel(vehicleState,manageFleetService);
}
private string _carbrand { get; set; } //if is problem with added to database look here
private string _vin { get; set; }
private string _milage { get; set; }
private string _enigneNumber { get; set; }
private string _engineCapacity { get; set; }
private string _registrationNumber { get; set; }
private DateTime _firstRegistration { get; set; }
private DateTime _yearPurchase { get; set; }
private DateTime _yearProduction { get; set; }
private byte [] _imageCar { get; set; }
public string CarBrand
{
get
{
return _carbrand;
}
set
{
_carbrand = value;
OnPropertyChanged(nameof(CarBrand));
}
}
public string VIN
{
get
{
return _vin;
}
set
{
_vin = value;
OnPropertyChanged(nameof(VIN));
}
}
public string Milage
{
get
{
return _milage;
}
set
{
_milage = value;
OnPropertyChanged(nameof(Milage));
}
}
public string EnigneNumber
{
get
{
return _enigneNumber;
}
set
{
_enigneNumber = value;
OnPropertyChanged(nameof(EnigneNumber));
}
}
public string EngineCapacity
{
get
{
return _engineCapacity;
}
set
{
_engineCapacity = value;
OnPropertyChanged(nameof(EngineCapacity));
}
}
public string RegistrationNumber
{
get
{
return _registrationNumber;
}
set
{
_registrationNumber = value;
OnPropertyChanged(nameof(RegistrationNumber));
}
}
public DateTime FirstRegistration
{
get
{
if(_firstRegistration.Year == 1) { return DateTime.Now; }
return _firstRegistration;
}
set
{
_firstRegistration = value;
OnPropertyChanged(nameof(FirstRegistration));
}
}
public DateTime YearPurchase
{
get
{
if(_yearPurchase.Year == 1) { return DateTime.Now; }
return _yearPurchase;
}
set
{
_yearPurchase = value;
OnPropertyChanged(nameof(YearPurchase));
}
}
public DateTime YearProduction
{
get
{
if (_yearProduction.Year == 1) { return DateTime.Now; }
return _yearProduction;
}
set
{
_yearProduction = value;
OnPropertyChanged(nameof(YearProduction));
}
}
public byte [] ImageCar
{
get
{
return _imageCar;
}
set
{
_imageCar = value;
OnPropertyChanged(nameof(ImageCar));
}
}
Below is the accepted answer but as you can see from the comments my statements are not true.
You have to bind to an ObservableCollection<T> for the control to subscribe to changes to the collection. In your case you bind to IEnumerable<T> so the control is populated from this list once. Changes to the ObservableCollection<T> backing the IEnumerable<T> are never seen by the control.
public IEnumerable<DisplayManageFleetViewModel> Vehicles => _manageFleetViewModel;
Simply change this to
public ObservableCollection<DisplayManageFleetViewModel> Vehicles => _manageFleetViewModel;
Or perhaps even better get rid of the _manageFleetViewModel field and change Vehicles:
public ObservableCollection<DisplayManageFleetViewModel> Vehicles { get; }
Then use Vehicles instead of _manageFleetViewModel in your code.

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.

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

How to bind an integer to a WPF template

I can't bind an integer variable to the template.
My C# code looks like below:
class Task
{
public string name;
public string desc;
public int pr;
public string TaskName
{
get { return name; }
set { name = value; }
}
public string Description
{
get { return desc; }
set { desc = value; }
}
public int Priority
{
get { return pr; }
set { pr = value; }
}
public Task(string name, string description, int pr)
{
this.TaskName = name;
this.Description = description;
this.Priority = pr;
}
}
and the XAML code is
<DataTemplate x:Key="myTaskTemplate">
<Border Name="border" BorderBrush="DarkSlateBlue" BorderThickness="2"
CornerRadius="2" Padding="5" Margin="5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Padding="0,0,5,0" Text="Task Name:"/>
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Path=TaskName}"/>
<TextBlock Grid.Row="1" Grid.Column="0" Padding="0,0,5,0" Text="Description:"/>
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Path=Description}"/>
<TextBlock Grid.Row="2" Grid.Column="0" Padding="0,0,5,0" Text="Priority:"/>
<TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Path=Priority}"/>
</Grid>
</Border>
</DataTemplate>
There is always "0" for the Priority column now. The other binding variables are displayed correctly, but they are strings.
Ussualy the ViewModel should implement INotifyPropertyChanged in order to propagate changes in properties to the view.
This being said, your class should look like this:
class Task : INotifyPropertyChanged
{
public string name;
public string desc;
public int pr;
public string TaskName
{
get { return name; }
set
{
name = value;
OnPropertyChanged("TaskName");
}
}
public string Description
{
get { return desc; }
set
{
desc = value;
OnPropertyChanged("Description");
}
}
public int Priority
{
get { return pr; }
set
{
pr = value;
OnPropertyChanged("Priority");
}
}
public Task(string name, string description, int pr)
{
this.TaskName = name;
this.Description = description;
this.Priority = pr;
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string pName)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(pName));
}
}
}
you didn't do any thing wrong, But check your code because the priority is overwritten in some where else the clue of that is your other binding works fine, don't forget to change your binding in all the property to be like ControlProperty="{Binding ClassProperty,UpdateSourceTrigger=PropertyChanged}"

Categories

Resources