Set two way binding numbers position xamarin - xamarin

I create pin combination layout like
Image
Code:
<StackLayout>
<Grid>
<Grid Margin="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button x:Name="btn7" Text="7" HeightRequest="160" WidthRequest="180" Margin="10" BackgroundColor="White" FontSize="50" />
<Button x:Name="btn8" Text="8" HeightRequest="160" WidthRequest="180" Margin="10" Grid.Column="1" BackgroundColor="White" FontSize="50" />
<Button x:Name="btn9" Text="9" HeightRequest="160" WidthRequest="180" Margin="10" Grid.Column="2" BackgroundColor="White" FontSize="50"/>
<Button Text="6" HeightRequest="160" WidthRequest="180" Margin="10" Grid.Column="2" Grid.Row="1" BackgroundColor="White" FontSize="50"/>
<Button Text="5" HeightRequest="160" WidthRequest="180" Margin="10" Grid.Column="1" Grid.Row="1" BackgroundColor="White" FontSize="50" />
<Button Text="4" HeightRequest="160" WidthRequest="180" Margin="10" Grid.Row="1" BackgroundColor="White" FontSize="50" />
<Button Text="1" HeightRequest="160" WidthRequest="180" Margin="10" Grid.Row="2" BackgroundColor="White" FontSize="50" />
<Button Text="2" HeightRequest="160" WidthRequest="180" Margin="10" Grid.Row="2" Grid.Column="1" BackgroundColor="White" FontSize="50" />
<Button Text="3" HeightRequest="160" WidthRequest="180" Margin="10" Grid.Row="2" Grid.Column="2" BackgroundColor="White" FontSize="50" />
<Button Text="0" HeightRequest="160" WidthRequest="180" Margin="10" Grid.Row="3" Grid.Column="1" BackgroundColor="White" FontSize="50" />
<Button Text="Ok" HeightRequest="160" WidthRequest="180" Margin="10" Grid.Row="3" BackgroundColor="White" FontSize="50"/>
<Button Text="Clear" HeightRequest="160" WidthRequest="180" Margin="10" Grid.Row="3" Grid.Column="2" BackgroundColor="White" FontSize="50" />
</Grid>
</Grid>
</StackLayout>
I want to do all number buttons random positions so I want to have 0,1,2,3,4,5,6,7,8,9 but in different position every time I access this view. I start with two binding class and I have structure like:
public class PinPageViewModel : BaseViewModel
{
public PinPageViewModel()
{
_ = LoadItems();
}
public PinPageViewModel(INavigation navigation)
{
_ = LoadItems();
Navigation = navigation;
}
public INavigation Navigation { get; set; }
private async Task LoadItems()
{
try
{
}
catch (Exception ex)
{
return;
}
}
}
So what I need to do to achieve that? I mean what I need to do in each button of stacklayout, then how can I receive in binding view model then set random text, and finally a function to know which button is pressed?
UPDATE
As comment bellow I have some questions, each button should have Text="{Binding Number}" (All buttons should have the same one)?
Then I change ViewModel as:
public PinPageViewModel()
{
_ = LoadItems();
}
public PinPageViewModel(INavigation navigation)
{
_ = LoadItems();
Navigation = navigation;
}
public INavigation Navigation { get; set; }
private int _number;
public int Number
{
get { return _number; }
set { SetProperty(ref _number, value, nameof(Number)); }
}
private async Task LoadItems()
{
try
{
SetNumber();
}
catch (Exception ex)
{
return;
}
}
private void SetNumber()
{
int Min = 0;
int Max = 9;
Random randNum = new Random();
int[] test2 = Enumerable
.Repeat(0, 5)
.Select(i => randNum.Next(Min, Max))
.ToArray();
//How can I assign a number to each button?
}
}
How can I assign button value to each button after random numbers? Regards

create a list of your numbers
public List<string> data { get; set; } = new List<string>{"0", "1", ... "9" };
randomize the order
in your XAML, bind each button to an element of the list
<Button Text="{Binding data[0]}" Clicked="ButtonClick" ... />
...
<Button Text="{Binding data[9]}" Clicked="ButtonClick" ... />
then in your click handler
protected void ButtonClick(object sender, EventArgs args)
{
var button = (Button)sender;
var number = button.Text;
}

Related

Xamarin App opens different Page from Navigation.PushAsync() Page

Description
Xamarin application opens different Page upon NavigationPage.Pushaync().
NavigationPage.Asyncpush() is called within a ButtonClicked Method.
That different page used to be the one being pushed but it no longer is.
ViewModel.cs
private async void OnAboutUsClicked()
{
var modifiedContactUs = new ModifiedContactUs() { BackgroundColor = ResourceColourModel.BackgroundColor };
await Application.Current.MainPage.Navigation.PushAsync(modifiedContactUs);
}
ModifiedContactUs.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Project.Views.Pages.ModifiedContact"
xmlns:mapObject="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps">
<ContentPage.Content>
<StackLayout>
<Grid BackgroundColor="white">
<mapObject:Map x:Name="mapId" HasZoomEnabled="True" MapType="Street">
</mapObject:Map>
</Grid>
</StackLayout>
</ContentPage.Content>
</ContentPage>
ModifiedContactUs.xaml.cs
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace Project.Views.Pages
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ModifiedContactUs : ContentPage
{
public ModifiedContactUs()
{
InitializeComponent();
}
}
ContactUs.xaml(The different Page)
<?xml version="1.0" encoding="utf-8" ?>
<customControl:CustomContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:map ="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps"
xmlns:ffimageloading="clr-namespace:FFImageLoading.Svg.Forms;assembly=FFImageLoading.Svg.Forms"
xmlns:customControl="clr-namespace:Project.CustomControls.Renderers"
xmlns:templates_navbar="clr-namespace:Project.Views.Templates.Menus"
xmlns:fontAwesome="clr-namespace:Project._Utilities"
mc:Ignorable="d"
x:Class="Project.Views.Pages.ContactUs"
>
<ContentPage.Content>
<StackLayout BackgroundColor="Transparent" Spacing="0">
<templates_navbar:NavBar DotMenu_IsVisible="False" BackButton_IsVisible="True"/>
<Grid BackgroundColor="white">
<Grid.RowDefinitions>
<RowDefinition Height=".33*"/>
<RowDefinition Height=".07*"/>
<RowDefinition Height=".6*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".7*"/>
<ColumnDefinition Width=".3*"/>
</Grid.ColumnDefinitions>
<StackLayout Grid.Column="0" Padding="10">
<StackLayout>
<Label
Text="Company Name"
FontAttributes="Bold"
FontSize="Medium"
FontFamily="Lato-Bold"
VerticalOptions="CenterAndExpand"
HorizontalOptions="StartAndExpand"
/>
<Label
Text="{Binding Address}"
FontFamily="Lato-Bold"
VerticalOptions="CenterAndExpand"
HorizontalOptions="StartAndExpand"
/>
</StackLayout>
<StackLayout>
<Label
Text="Opening Times"
FontAttributes="Bold"
FontSize="Medium"
FontFamily="Lato-Bold"
VerticalOptions="CenterAndExpand"
HorizontalOptions="StartAndExpand"
/>
<Label
x:Name="weekdays_lbl"
Text="{Binding Weekday}"
FontFamily="Lato-Bold"
VerticalOptions="CenterAndExpand"
HorizontalOptions="StartAndExpand"
/>
<Label
x:Name="weekend_lbl"
Text="{Binding Weekend}"
FontFamily="Lato-Bold"
VerticalOptions="CenterAndExpand"
HorizontalOptions="StartAndExpand"
/>
</StackLayout>
</StackLayout>
<StackLayout Grid.Column="1">
<StackLayout VerticalOptions="CenterAndExpand">
<Button
x:Name="CallUsBtn"
Text="Call Us"
TextColor="White"
BackgroundColor="{StaticResource PrimaryColour}"
FontFamily="Lato-Bold"
FontSize="12"
BorderWidth="2"
BorderColor="White"
Margin="1"
CornerRadius="22"
Command="{Binding PhoneCommand}"
/>
<Button
x:Name="MessageUsBtn"
Text="Message"
TextColor="White"
BackgroundColor="{StaticResource PrimaryColour}"
FontFamily="Lato-Bold"
FontSize="12"
BorderWidth="2"
BorderColor="White"
Margin="1"
CornerRadius="22"
Command="{Binding EmailCommand}"
/>
<Button
x:Name="RequestCallBack"
Text="Request CallBack"
TextColor="White"
BackgroundColor="{StaticResource AccentColour}"
FontFamily="Lato-Bold"
FontSize="11"
BorderWidth="2"
BorderColor="White"
Margin="1"
CornerRadius="22"
Command="{Binding CallbackCommand}"
/>
</StackLayout>
</StackLayout>
</Grid>
<Grid Grid.Row="1" Padding="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".25*"/>
<ColumnDefinition Width=".25*"/>
<ColumnDefinition Width=".25*"/>
<ColumnDefinition Width=".25*"/>
</Grid.ColumnDefinitions>
<StackLayout Grid.Column="0">
<Grid VerticalOptions="CenterAndExpand">
<Image
Source="{FontImage FontFamily={StaticResource MaterialFontFamily},
Glyph={x:Static fontAwesome:IconFonts.Facebook}, Color=#1877F2,Size=60}"
HeightRequest="80"
/>
<Button Clicked="SocialMediaBtnHandler" BackgroundColor="Transparent" Margin="5, 0" CommandParameter="facebook"/>
</Grid>
</StackLayout>
<StackLayout Grid.Column="1">
<Grid VerticalOptions="CenterAndExpand">
<Image
Source="{FontImage FontFamily={StaticResource MaterialFontFamily},
Glyph={x:Static fontAwesome:IconFonts.Twitter}, Color=#00ACED, Size=60}"/>
<Button Clicked="SocialMediaBtnHandler" BackgroundColor="Transparent" Margin="5, 0" CommandParameter="twitter"/>
</Grid>
</StackLayout>
<StackLayout Grid.Column="2">
<Grid VerticalOptions="CenterAndExpand">
<Image
Source="{FontImage FontFamily={StaticResource MaterialFontFamily},
Glyph={x:Static fontAwesome:IconFonts.Linkedin}, Color=#0E76A8, Size=60}"/>
<Button Clicked="SocialMediaBtnHandler" BackgroundColor="Transparent" Margin="5, 0" CommandParameter="linkedIn"/>
</Grid>
</StackLayout>
<StackLayout Grid.Column="3">
<Grid VerticalOptions="CenterAndExpand" Padding="2">
<ffimageloading:SvgCachedImage
Source="social_logo_instagram.png"
HeightRequest="40"/>
<Button Clicked="SocialMediaBtnHandler" BackgroundColor="Transparent" Margin="5, 0" CommandParameter="instagram"/>
</Grid>
</StackLayout>
</Grid>
<Grid Grid.Row="2">
<Grid>
<StackLayout Grid.Row="0" Padding="5">
<map:Map x:Name="mapObject" HasZoomEnabled="True" MapType="Street">
<map:Map.ItemTemplate>
<DataTemplate>
<map:Pin
Position="{Binding Position}"
Address="{Binding Address}"
Label="{Binding PlaceName}"
/>
</DataTemplate>
</map:Map.ItemTemplate>
</map:Map>
</StackLayout>
</Grid>
</Grid>
</Grid>
<AbsoluteLayout BackgroundColor="Red" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" AbsoluteLayout.LayoutBounds="0, 0, 1, 1" AbsoluteLayout.LayoutFlags="SizeProportional">
</AbsoluteLayout>
</StackLayout>
</ContentPage.Content>
</customControl:CustomContentPage>
ContactUs.xaml.cs (The different page)
using Project._SharedData;
using Project.CustomControls.Renderers;
using Project.Models;
using Project.ViewModels;
using Rg.Plugins.Popup.Services;
using System;
using Xamarin.Essentials;
using Xamarin.Forms;
using Xamarin.Forms.Maps;
using Xamarin.Forms.Xaml;
namespace Project.Views.Pages
{
[XamlCompilation(XamlCompilationOptions.Compile)]
[System.ComponentModel.DesignTimeVisible(false)]
public partial class ContactUsPage : CustomContentPage
{
ContactUsVM _ContactUsVM;
public ContactUsPage()
{
InitializeComponent();
BindingContext = _ContactUsVM = new ContactUsVM();
initMap();
configureDisplay();
setFontOpeningTime();
}
protected override void OnAppearing()
{
base.OnAppearing();
_ContactUsVM.OnAppearing();
configureDisplay();
}
protected override void OnDisappearing()
{
base.OnDisappearing();
_ContactUsVM.OnDisappearing();
try
{
if (PopupNavigation.Instance != null)
PopupNavigation.Instance.PopAsync(true);
}
catch (Exception) { }
}
private void setFontOpeningTime()
{
DayOfWeek day = DateTime.Now.DayOfWeek;
// Set the font based on whether current day is weekday or weekend
if ((day == DayOfWeek.Saturday) || (day == DayOfWeek.Sunday))
{
weekend_lbl.FontAttributes = FontAttributes.Bold;
}
else
{
weekdays_lbl.FontAttributes = FontAttributes.Bold;
}
}
private void configureDisplay()
{
if (!string.IsNullOrEmpty(SharedPrefs.UserSessionEmail))
{
RequestCallBack.IsVisible = true;
MessageUsBtn.Text = "Email";
}
else
{
RequestCallBack.IsVisible = false;
MessageUsBtn.Text = "Message";
}
}
private async void SocialMediaBtnHandler(object sender, EventArgs e)
{
string socialMediaName = (sender as Button).CommandParameter.ToString().ToLower();
await Launcher.OpenAsync(SocialMediaModel.WebLink(socialMediaName));
}
private void initMap()
{
try
{
double latitude = Convert.ToDouble(SharedData.CompanyDetailsList[0].Latitude);
double longitude = Convert.ToDouble(SharedData.CompanyDetailsList[0].Longitude);
mapObject.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(latitude, longitude), Distance.FromMeters(100)));
mapObject.ItemsSource = SharedData.CompanyDetailsList;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
Expected behavior
To navigate to a new Page named ModifiedContactUs
Actual behavior:
Navigates to page called named ContactUs
Basic Information:
Android Build:
-minimum level 21
-Target level 30
Devices:
-Huawei Y6 2019
-API level 29
-Pixel 5
-API level 30
Notes
This question is different to from the first question I asked recently (Where the device crashes). This is behavior happens on all devices I test on except the one from that first question
Expected behavior
To navigate to a new Page named ModifiedContactPage
Actual behavior:
Navigates to page called named ContactUsPage
From your code I saw you just push to ModifiedContactUs not ModifiedContactPage .
var modifiedContactUs = new ModifiedContactUs() { BackgroundColor = ResourceColourModel.BackgroundColor };
await Application.Current.MainPage.Navigation.PushAsync(modifiedContactUs);
Suggestion
Try to add breakpoint to see if it triggers button click event es expected .
Delete the old class and try again .
Delete the app from the device and try again .
This worked: Clone the repo into a new folder as a new project and copy the files and changes to this new repo.
Attempted configuration solutions that did not work: Restarting visual studio. Untick and Tick Debug Mode. Untick and tick Deploy in Configuration Manager under Build. In Android Properties> android Options making sure debugging is checked and debugger is Xamarin.

At a time only one expander expand on xamarin form

On my page there is a 4 expander ,I want to write a code for at a time one expander is expand ,What can I do for this scenario please help me ,For more clarifications I have a add image of expanders ,In this given code there is a one expander show ,but this type of a 4 expander available on my page and i want to expand one at a time
enter image description here
<StackLayout IsVisible="{Binding Synonyms,Converter={x:StaticResource CorrectionTypeVisiableConverter}}" Orientation="Vertical" VerticalOptions="StartAndExpand" HorizontalOptions="FillAndExpand">
<xct:Expander ExpandAnimationEasing="CubicIn"
ExpandAnimationLength="500"
CollapseAnimationEasing="CubicOut"
CollapseAnimationLength="500">
<xct:Expander.Header>
<Frame HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" BorderColor="#F0F0F0" HasShadow="False" >
<StackLayout Orientation="Horizontal" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<xct:BadgeView Text="{Binding Synonyms,Converter={StaticResource CorrectionCountBadgeConverter}}" BackgroundColor="#FADBD8" BadgePosition="TopLeft" TextColor="#E74C3C" HorizontalOptions="Start" FontSize="16" AutoHide="True" VerticalOptions="CenterAndExpand">
<Label Text=""></Label>
</xct:BadgeView>
<Label Text="{x:Static resources:AppResources.Synonyms}"
FontAttributes="Bold" VerticalOptions="CenterAndExpand"
FontSize="Medium" Style="{StaticResource MenueLableStyle}" HorizontalOptions="StartAndExpand" />
<Image Source="Expand.png"
HorizontalOptions="EndAndExpand"
VerticalOptions="CenterAndExpand">
<Image.Triggers>
<DataTrigger TargetType="Image"
Binding="{Binding Source={RelativeSource AncestorType={x:Type xct:Expander}}, Path=IsExpanded,Mode=OneTime}"
Value="True">
<Setter Property="Source"
Value="collapse.png" />
</DataTrigger>
</Image.Triggers>
</Image>
</StackLayout>
</Frame>
</xct:Expander.Header>
<xct:Expander.ContentTemplate>
<DataTemplate>
<StackLayout BindableLayout.ItemsSource="{Binding Synonyms}" VerticalOptions="StartAndExpand" HorizontalOptions="FillAndExpand">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Frame HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" BorderColor="#F0F0F0" HasShadow="False" >
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<StackLayout Grid.Row="0" Orientation="Horizontal">
<Label Text="{Binding s}" HorizontalOptions="Start" VerticalOptions="Center">
</Label>
<Label Text="--->" HorizontalOptions="Start" VerticalOptions="Center"></Label>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<xct:BadgeView Grid.Column="0" Text="" BackgroundColor="#FADBD8" BadgePosition="TopRight" TextColor="#E74C3C" FontSize="14" HorizontalOptions="CenterAndExpand" AutoHide="True" VerticalOptions="Center" Background="#FADBD8" WidthRequest="80" HeightRequest="25">
<Label Text="{Binding c}"></Label>
</xct:BadgeView>
<ImageButton Grid.Column="0" Source="Storyedit.png"
HorizontalOptions="EndAndExpand" VerticalOptions="Center" WidthRequest="12" HeightRequest="12"/>
</Grid>
<ImageButton Source="Info.png" Command="{Binding Path=BindingContext.CorrectionInfoCommand,Source={x:Reference Name=storyView}}"
CommandParameter="{Binding .}" HorizontalOptions="EndAndExpand"/>
</StackLayout>
<Button Grid.Row="1" Text="{x:Static resources:AppResources.IgnoreButton}" Style="{StaticResource CancelButton}" VerticalOptions="EndAndExpand" HorizontalOptions="CenterAndExpand" ></Button>
<Button Grid.Row="1" Text="{x:Static resources:AppResources.AcceptButton}" Style="{StaticResource AcceptButton}" VerticalOptions="EndAndExpand" HorizontalOptions="StartAndExpand" ></Button>
<FlexLayout IsVisible="False" Grid.Row="3" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" AlignItems="Start" AlignContent="Center" Direction="Row" Wrap="Wrap" JustifyContent="Center">
<Button Text="{x:Static resources:AppResources.IgnoreButton}" Padding="5" Style="{StaticResource CancelButton}" HorizontalOptions="StartAndExpand"></Button>
<Button Text="{x:Static resources:AppResources.IgnoreAllButton}" Style="{StaticResource CancelButton}" HorizontalOptions="CenterAndExpand" Padding="5"></Button>
<Button Text="{x:Static resources:AppResources.AcceptButton}" Style="{StaticResource AcceptButton}" HorizontalOptions="StartAndExpand" Padding="5"></Button>
<Button Text="{x:Static resources:AppResources.AcceptAllButton}" Style="{StaticResource AcceptButton}" HorizontalOptions="CenterAndExpand" Padding="5"></Button>
</FlexLayout>
</Grid>
</Frame>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</DataTemplate>
</xct:Expander.ContentTemplate>
</xct:Expander>
</StackLayout>
You could binding true or false for the IsExpanded property to indicate that the Expander is expanded or collapsed.
I make a simple example for your reference.
Model:
public class Model : INotifyPropertyChanged
{
#region fields
public string _synonyms;
public string _s;
public bool _isexpand;
#endregion
public string Synonyms
{
get { return _synonyms; }
set { _synonyms = value; OnPropertyChanged("Synonyms"); }
}
public string s
{
get { return _s; }
set { _s = value; OnPropertyChanged("s"); }
}
public bool ISexpand
{
get { return _isexpand; }
set { _isexpand = value; OnPropertyChanged("ISexpand"); }
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
ViewModel:
public class ViewModel1
{
public ObservableCollection<Model> models { get; set; }
public ViewModel1()
{
CreateCollection();
}
public void CreateCollection()
{
models = new ObservableCollection<Model>()
{
new Model(){ Synonyms="Synonym1", s="A", ISexpand=false},
new Model(){ Synonyms="Synonym2", s="B",ISexpand=false},
new Model(){ Synonyms="Synonym3", s="C",ISexpand=false},
new Model(){ Synonyms="Synonym4", s="D",ISexpand=false},
new Model(){ Synonyms="Synonym5", s="E",ISexpand=false},
};
}
}
Xaml:
<ContentPage.BindingContext>
<local:ViewModel1></local:ViewModel1>
</ContentPage.BindingContext>
<ContentPage.Content>
<StackLayout x:Name="stacklayout" BindableLayout.ItemsSource="{Binding models}" Orientation="Vertical" VerticalOptions="StartAndExpand" HorizontalOptions="FillAndExpand">
<BindableLayout.ItemTemplate>
<DataTemplate>
<xct:Expander IsExpanded="{Binding ISexpand}" Tapped="Expander_Tapped" >
<xct:Expander.Header>
<Label Text="{Binding Synonyms}"></Label>
</xct:Expander.Header>
<xct:Expander.ContentTemplate>
<DataTemplate>
<Label Text="{Binding s}"></Label>
</DataTemplate>
</xct:Expander.ContentTemplate>
</xct:Expander>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</ContentPage.Content>
Code behind:
public partial class Page10 : ContentPage
{
ViewModel1 viewModel1=new ViewModel1();
public Page10()
{
InitializeComponent();
}
int i = 0;
private void Expander_Tapped(object sender, EventArgs e)
{
var expander = sender as Expander;
var label = expander.Header as Label;
var list = viewModel1.models;
foreach (var item in viewModel1.models)
{
if (item.Synonyms == label.Text)
{
item.ISexpand = true;
if (i >= 1)
{
foreach (var item1 in viewModel1.models.ToList())
{
if (item1.Synonyms!= label.Text)
{
item1.ISexpand = false;
}
}
BindableLayout.SetItemsSource(stacklayout, viewModel1.models);
}
}
}
i++;
}
}
OutPut:
https://imgur.com/4D6x1yB

Fire a command on tap in ListView.ItemSource

In a Xamarin project I have this ListView inside a view called menu.xaml:
<ListView x:Name="listView" x:FieldModifier="public">
<ListView.ItemsSource>
<x:Array Type="{x:Type local1:MasterPageItem}">
<local1:MasterPageItem Title="foo" TargetType="{x:Type local:FooPage}" />
<local1:MasterPageItem Title="bar" TargetType="{x:Type local:BarPage}" />
<local1:MasterPageItem Title="logout" TargetType="{x:Type local:LogoutPage}" />
</x:Array>
</ListView.ItemsSource>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Padding="5,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Source="{Binding IconSource}" />
<Label Grid.Column="1" Text="{Binding Title}" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
These produces this list:
In my viewmodel, I have this command:
class MasterViewModel : BaseViewModel
{
public ICommand LogoutActivity { get; private set; }
public MasterViewModel()
{
LogoutActivity = new Command(async () => await LogoutAsync());
}
}
Tapping one of these items opens a corresponding page. I want the logout link to fire a command instead of opening a page. How do I accomplish this?
You can add Tapped Gesture Recognizer to your grid:
<Grid Padding="5,10">
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding LoginActivity}" CommandParameter="{Binding .}">
</TapGestureRecognizer>
</Grid.GestureRecognizers>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Source="{Binding IconSource}" />
<Label Grid.Column="1" Text="{Binding Title}" />
</Grid>
For executing specific action for menu items, you can add unique property to your MasterPageItem model and set for each of them.
public partial class MainPage : MasterDetailPage
{
public MainPage ()
{
masterPage.listView.ItemSelected += OnItemSelected;
}
void OnItemSelected (object sender, SelectedItemChangedEventArgs e)
{
var item = e.SelectedItem as MasterPageItem;
if (item != null) {
// Check here if is the logout link that is clicked and perform the required a action
}
}
}

How can retrieve data from various entries (each single-line), calculate it, then be able to display results in real time?

I would like to know a way to able to retrieve data from various entries from a Grid Layout and have their values ready to calculate inside other classes/methods. I want the results to automatically change depending on what you enter in the Score, ScoreGot and Weight of each grade.
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="GradeThisForMe.GradeCalculator"
NavigationPage.HasNavigationBar="False"
BackgroundImage="WallpaperBlueSkyBlurMedium.png">
<StackLayout>
<ScrollView>
<Grid x:Name="tableGrid" RowSpacing="0" ColumnSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Text="Target Grade: " Style="{StaticResource GridTopLabelStyle}" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" />
<Entry Text="{Binding TargetGrade}" Style="{StaticResource GridTopEntryStyle}" Grid.Row="0" Grid.Column="2" Grid.ColumnSpan="1"/>
<Label Text="Current Grade: " Style="{StaticResource GridTopLabelStyle}" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" />
<Label Text="{Binding AverageGrade}" Style="{StaticResource GridTopLabelStyle}" Grid.Row="1" Grid.Column="2" Grid.ColumnSpan="2"/>
<Label Text="You need: " Style="{StaticResource GridTopLabelStyle}" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" />
<Label Text="{Binding GradeNeeded}" Style="{StaticResource GridTopLabelStyle}" Grid.Row="2" Grid.Column="2" Grid.ColumnSpan="2"/>
<Label Text="#" Style="{StaticResource GridBottomLabelStyle}" Grid.Row="3" Grid.Column="0"/>
<Label Text="Score" Style="{StaticResource GridBottomLabelStyle}" Grid.Row="3" Grid.Column="1"/>
<Label Text="Score Got" Style="{StaticResource GridBottomLabelStyle}" Grid.Row="3" Grid.Column="2"/>
<Label Text="Weight" Style="{StaticResource GridBottomLabelStyle}" Grid.Row="3" Grid.Column="3"/>
<Entry Text="{Binding Grade1Name}" Style="{StaticResource GridBottomEntryStyle}" Placeholder="Grade#1" Grid.Row="4" Grid.Column="0"/>
<Entry Text="{Binding Score1}" Style="{StaticResource GridNumericEntryStyle}" Grid.Row="4" Grid.Column="1"/>
<Entry Text="{Binding ScoreGot1}" Style="{StaticResource GridNumericEntryStyle}" Grid.Row="4" Grid.Column="2"/>
<Entry Text="{Binding Weight1}" Style="{StaticResource GridNumericEntryStyle}" Grid.Row="4" Grid.Column="3"/>
<Entry Style="{StaticResource GridBottomEntryStyle}" Placeholder="Grade#2" Grid.Row="5" Grid.Column="0"/>
<Entry Style="{StaticResource GridNumericEntryStyle}" Grid.Row="5" Grid.Column="1"/>
<Entry Style="{StaticResource GridNumericEntryStyle}" Grid.Row="5" Grid.Column="2"/>
<Entry Style="{StaticResource GridNumericEntryStyle}" Grid.Row="5" Grid.Column="3"/>
<Entry Style="{StaticResource GridBottomEntryStyle}" Placeholder="Grade#3" Grid.Row="6" Grid.Column="0"/>
<Entry Style="{StaticResource GridNumericEntryStyle}" Grid.Row="6" Grid.Column="1"/>
<Entry Style="{StaticResource GridNumericEntryStyle}" Grid.Row="6" Grid.Column="2"/>
<Entry Style="{StaticResource GridNumericEntryStyle}" Grid.Row="6" Grid.Column="3"/>
<Entry Style="{StaticResource GridBottomEntryStyle}" Placeholder="Grade#4" Grid.Row="7" Grid.Column="0"/>
<Entry Style="{StaticResource GridNumericEntryStyle}" Grid.Row="7" Grid.Column="1"/>
<Entry Style="{StaticResource GridNumericEntryStyle}" Grid.Row="7" Grid.Column="2"/>
<Entry Style="{StaticResource GridNumericEntryStyle}" Grid.Row="7" Grid.Column="3"/>
<Entry Style="{StaticResource GridBottomEntryStyle}" Placeholder="Grade#5" Grid.Row="8" Grid.Column="0"/>
<Entry Style="{StaticResource GridNumericEntryStyle}" Grid.Row="8" Grid.Column="1"/>
<Entry Style="{StaticResource GridNumericEntryStyle}" Grid.Row="8" Grid.Column="2"/>
<Entry Style="{StaticResource GridNumericEntryStyle}" Grid.Row="8" Grid.Column="3"/>
<Entry Style="{StaticResource GridBottomEntryStyle}" Placeholder="Grade#6" Grid.Row="9" Grid.Column="0"/>
<Entry Style="{StaticResource GridNumericEntryStyle}" Grid.Row="9" Grid.Column="1"/>
<Entry Style="{StaticResource GridNumericEntryStyle}" Grid.Row="9" Grid.Column="2"/>
<Entry Style="{StaticResource GridNumericEntryStyle}" Grid.Row="9" Grid.Column="3"/>
</Grid>
</ScrollView>
<Button Text="Calculate"
Style="{StaticResource PrimaryButton}"/>
</StackLayout>
</ContentPage>
For testing purposes, my goal is to change and display the results of AverageGrade in real time after entering the score and score got in grade#1. To notice property changes, the value has to be a string. To calculate results, In Grade1Total, I tried to convert the Score1 and ScoreGot1 values temporarily into double. After converting the calculation results to string, it never shows up on display. What do you recommend I should do?
Note: I know that some parts of the code like Calculate button are incomplete or unnecessary. My priority right now is to fix this situation.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace GradeThisForMe
{
public class AddGradesDetails: INotifyPropertyChanged
{
string targetGrade;
string grade1_Name;
string score1;
double dbl_score1;
string score_got1;
double dbl_score_got1;
string weight1;
string total_grade1;
double dbl_total_grade1;
string decimal_weight1;
string average_grade;
string grade_needed;
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged([CallerMemberName] string total_grade1 = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(total_grade1));
}
public string Grade1Name
{
get { return grade1_Name; }
set
{
grade1_Name = value;
OnPropertyChanged(Grade1Name);
}
}
public string Score1
{
get { return score1; }
set
{
score1 = value;
OnPropertyChanged(Score1);
OnPropertyChanged(nameof(AverageGrade));
}
}
public string ScoreGot1
{
get { return score_got1; }
set
{
score_got1 = value;
OnPropertyChanged(ScoreGot1);
OnPropertyChanged(nameof(AverageGrade));
}
}
public string Weight1
{
get { return weight1; }
set
{
weight1 = value;
OnPropertyChanged(Weight1);
OnPropertyChanged(nameof(AverageGrade));
}
}
public string Grade1Total
{
get { return total_grade1; }
set
{
dbl_score1 = Convert.ToDouble(Score1);
dbl_score_got1 = Convert.ToDouble(ScoreGot1);
dbl_total_grade1 = ((dbl_score_got1 / dbl_score1)*100);
total_grade1 = Convert.ToString(dbl_score1);
OnPropertyChanged(Grade1Total);
OnPropertyChanged(nameof(AverageGrade));
}
}
public string AverageGrade
{
get { return $"{Grade1Total}"; }
set
{
OnPropertyChanged(nameof(AverageGrade));
}
}
public string TargetGrade
{
get { return targetGrade; }
set
{
targetGrade = value;
OnPropertyChanged(TargetGrade);
}
}
public string GradeNeeded
{
get { return grade_needed; }
set
{
}
}
}
}
Just update the value of in the binding model. Set the detailsModel as BindingContext and update the value of detailsModel.Result when you click Calculate button. Here is a simple example:
public partial class MainPage : ContentPage
{
AddGradesDetails detailsModel;
public MainPage()
{
InitializeComponent();
detailsModel = new AddGradesDetails();
detailsModel.Score1 = "1";
detailsModel.ScoreGot1 = "2";
detailsModel.Result = "";
BindingContext = detailsModel;
}
private void Button_Clicked(object sender, EventArgs e)
{
double result = Convert.ToDouble(detailsModel.Score1) + Convert.ToDouble(detailsModel.ScoreGot1);
detailsModel.Result = result.ToString();
}
}
And in xaml:
<StackLayout>
<ScrollView>
<Grid x:Name="tableGrid" RowSpacing="0" ColumnSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Text="Target Grade: " Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" />
<Entry Text="{Binding TargetGrade}" Grid.Row="0" Grid.Column="2" Grid.ColumnSpan="1"/>
<Label Text="Current Grade: " Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" />
<Label Text="{Binding AverageGrade}" Grid.Row="1" Grid.Column="2" Grid.ColumnSpan="2"/>
<Label Text="You need: " Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" />
<Label Text="{Binding GradeNeeded}" Grid.Row="2" Grid.Column="2" Grid.ColumnSpan="2"/>
<Label Text="#" Grid.Row="3" Grid.Column="0"/>
<Label Text="Score" Grid.Row="3" Grid.Column="1"/>
<Label Text="Score Got" Grid.Row="3" Grid.Column="2"/>
<Label Text="Weight" Grid.Row="3" Grid.Column="3"/>
<Entry Text="{Binding Grade1Name}" Placeholder="Grade#1" Grid.Row="4" Grid.Column="0"/>
<Entry Text="{Binding Score1}" Grid.Row="4" Grid.Column="1"/>
<Entry Text="{Binding ScoreGot1}" Grid.Row="4" Grid.Column="2"/>
<Entry Text="{Binding Result}" Grid.Row="4" Grid.Column="3"/>
</Grid>
</ScrollView>
<Button Text="Calculate" Clicked="Button_Clicked"/>
</StackLayout>
The model:
public class AddGradesDetails : INotifyPropertyChanged
{
string grade1_Name { get; set; }
string score1 { get; set; }
string score_got1 { get; set; }
string result { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public string Grade1Name
{
get { return grade1_Name; }
set
{
grade1_Name = value;
OnPropertyChanged("Grade1Name");
}
}
public string Score1
{
get { return score1; }
set
{
if (value != score1)
{
score1 = value;
OnPropertyChanged("Score1");
}
}
}
public string ScoreGot1
{
get { return score_got1; }
set
{
score_got1 = value;
OnPropertyChanged("ScoreGot1");
}
}
public string Result
{
get { return result; }
set
{
result = value;
OnPropertyChanged("Result");
}
}
}

Xamarin Forms CollectionView TapGestureRecognizer not firing on label

I have a XF app with the following collection view defined. The 2nd label has a TapGestureRecognizer that doesn't fire DoSomethingInteresting in the model when I tap the label (trying this on Android). Can someone see what the issue is please?
A working sample can be cloned from here.
XAML
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:SampleApp"
x:Class="SampleApp.MainPage">
<StackLayout>
<CollectionView ItemsSource="{Binding GaugeSites}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="40" />
</Grid.RowDefinitions>
<Label Grid.Column="0"
Text="{Binding Description}"
FontSize="20"
Margin="10"
TextColor="Black"
FontAttributes="Bold" />
<Label Grid.Column="1"
Margin="10"
FontSize="20"
Text="Click Me!">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding DoSomethingInteresting}" />
</Label.GestureRecognizers>
</Label>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</ContentPage>
Model
namespace SampleApp
{
public class MainPageModel : FreshBasePageModel
{
public MainPageModel() : base()
{
GaugeSites = new List<GaugeSite>();
for (var index = 1; index <= 5; index++)
{
GaugeSites.Add(new GaugeSite()
{
Description = $"Gauge Site {index}"
});
}
}
public List<GaugeSite> GaugeSites { get; set; }
public Command DoSomethingInteresting
{
get
{
return new Command(() =>
{
});
}
}
}
[AddINotifyPropertyChangedInterface]
public class GaugeSite
{
public string Description { get; set; }
}
}
Maybe this is redundant but I will take my chances. As other answers indicated you need to set the source within your TapGestureRecognizer to the name of the CollectionView. However, it is probably useful to know which GaugeSite instance was associated with the CollectionView item whose TabGestureRecognizer was tapped. To add this info add a CommandParamter, i.e.
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding BindingContext.DoSomethingInteresting,
CommandParameter="{Binding}"
Source={x:Reference YourCollectionName}}" />
</Label.GestureRecognizers>
When it comes to the command you could use
DoSomethingInteresting = new Command<GaugeSite>((a) => DoSomething(a));
in your viewmodels contructor. And the method referenced by the lambda would be
void DoSomething(GaugeSite gaugeSite)
{
// ....
}
Hope this helps
I have download your sample, please take a look the following step.
1.Binding MainpageModel for MainPage bindingContext, add this line in MainPage.cs.
this.BindingContext = new MainPageModel();
2.Name Collectionview as collection1, then modify label command.
<CollectionView x:Name="collection1" ItemsSource="{Binding GaugeSites}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="40" />
</Grid.RowDefinitions>
<Label
Grid.Column="0"
Margin="10"
FontAttributes="Bold"
FontSize="20"
Text="{Binding Description}"
TextColor="Black" />
<Label
Grid.Column="1"
Margin="10"
FontSize="20"
Text="Click Me!">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding BindingContext.DoSomethingInteresting, Source={x:Reference collection1}}" />
</Label.GestureRecognizers>
</Label>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
Then you can try again.

Resources