How to pass the bound property with command to modify it - xamarin

i have a page with multiple labels that each have a different property bound to it and when tapped open up a prompt to modify their value. I can't figure out how to pass that property with the command so i can modify it and use this same command for all labels.
In ContentPage:
<Label x:Name="lblLevel" Text="{Binding Level}" FontSize="Large">
<Label.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding InputPopup}"
CommandParameter="{Binding Source={x:Reference lblLevel}, Path=Text}" />
</Label.GestureRecognizers>
</Label>
Command:
public ICommand InputPopup => new Command(
async () => {
PromptResult pResult = await UserDialogs.Instance.PromptAsync(new PromptConfig
{
InputType = InputType.Name,
OkText = "Confirm",
Title = "New value",
CancelText = "Cancel",
MaxLength = 1,
});
if (pResult.Ok && !string.IsNullOrWhiteSpace(pResult.Text))
{
//Todo: PropertyX (Level) = pResult.Text
}
}
);
Thank you

just bind the CommandParameter to the same property as the Label
Command="{Binding InputPopup}"
CommandParameter="{Binding Level}" />

So after trying a couple different things that i couldn't get to work i ended up using a switch, it's not pretty but atleast it works.
Command (in FreshMVVM ViewModel):
public ICommand EditValuePopupCommand => new Command<string>(
async (param) =>
{
PromptResult pResult = await UserDialogs.Instance.PromptAsync(new PromptConfig
{
InputType = InputType.Name,
OkText = "Confirm",
Title = $"Edit {param}",
CancelText = "Cancel",
MaxLength = 2,
});
if (pResult.Ok && !string.IsNullOrWhiteSpace(pResult.Text))
{
switch (param)
{
case "Level": Level = int.Parse(pResult.Text); break;
case "Strength": Strength = "Str: " + pResult.Text; break;
case "Dexterity": Dexterity = "Dex: " + pResult.Text; break;
case "Constitution": Constitution = "Con: " + pResult.Text; break;
case "Wisdom": Wisdom = "Wis: " + pResult.Text; break;
case "Intelligence": Intelligence = "Int: " + pResult.Text; break;
case "Charisma": Charisma = "Cha: " + pResult.Text; break;
case "AttackModifier": AttackModifier = "Attack: " + pResult.Text; break;
case "SpellAttackModifier": SpellAttackModifier = "Spell Attack: " + pResult.Text; break;
case "SecondaryAttackModifier": SecondaryAttackModifier = "Second Attack: " + pResult.Text; break;
case "SaveDC": SaveDC = "Second Attack: " + pResult.Text; break;
default:
Console.WriteLine("Default case");
break;
}
}
}
);
XAML:
<StackLayout Orientation="Horizontal" HorizontalOptions="CenterAndExpand">
<Frame Style="{StaticResource DefaultFrameStyle}">
<Label x:Name="lblStrength" Text="{Binding Strength}">
<Label.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding EditValuePopupCommand}"
CommandParameter="Strength" />
</Label.GestureRecognizers>
</Label>
</Frame>
<Frame Style="{StaticResource DefaultFrameStyle}">
<Label x:Name="lblDexterity" Text="{Binding Dexterity}">
<Label.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding EditValuePopupCommand}"
CommandParameter="Dexterity" />
</Label.GestureRecognizers>
</Label>
</Frame>

Related

Xamarin CarouselView throws OutOfRangeException when ItemsSource changes and Positon is not 0

I have a Xamarin Forms App with a Carousel View and my plan is to filter the result by the Priorities shown in a Bottom Tap Bar.
When the View is on the first card, everything works fine, but if you hit one of the filters from a different card, then the first one, a System.ArgumentOutOfRangeException exception got fired.
I tried already a lot of things to set the position of the Carousel View to 0, but in vain.
using the CarouselView_PositionChanged event => not working
using the TabHost_SelectedTabIndexChanged event => not working
setting the property of the CarouselView by the selectedIndex changed from the Tab View from the ViewModel => not working
turn it into a CollectionView and everything is working => just looks ugly 🤮
Here the page
<?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:android="clr-namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
xmlns:viewModels="clr-namespace:AmsXamarin.ViewModels"
xmlns:fontAwesome="clr-namespace:FontAwesome"
xmlns:cells="clr-namespace:AmsXamarin.Cells"
xmlns:tabs="http://sharpnado.com"
xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
x:Class="AmsXamarin.Views.SnagListX.SnagListPage"
x:Name="mySnagListPage">
<ContentPage.BindingContext>
<viewModels:SnagListViewModel />
</ContentPage.BindingContext>
<ContentPage.Resources>
<ResourceDictionary>
<xct:TabSelectionChangedEventArgs x:Key="TabSelectionChangedEventArgs" />
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.ToolbarItems>
<ToolbarItem Command="{Binding ShowMyJobsCommand}"
Order="Primary"
Priority="0"
Text="{Binding MyJobsTitle,Mode=TwoWay}">
</ToolbarItem>
<ToolbarItem Command="{Binding AddFaultCommand}"
Order="Primary"
Priority="0">
<ToolbarItem.IconImageSource>
<FontImageSource FontFamily="FAS"
Glyph="{x:Static fontAwesome:FontAwesomeIcons.Plus}"
Color="{AppThemeBinding Dark={StaticResource Third},Light={StaticResource Primary}}"
Size="Large" />
</ToolbarItem.IconImageSource>
</ToolbarItem>
<ToolbarItem Command="{Binding AcceptCommand}"
Order="Primary"
Priority="0">
<ToolbarItem.IconImageSource>
<FontImageSource FontFamily="FAS"
Glyph="{x:Static fontAwesome:FontAwesomeIcons.UserCheck}"
Color="{AppThemeBinding Dark={StaticResource Third},Light={StaticResource Primary}}"
Size="Large" />
</ToolbarItem.IconImageSource>
</ToolbarItem>
</ContentPage.ToolbarItems>
<ContentPage.Content>
<StackLayout>
<Label Style="{StaticResource LabelLarge}"
Text="Snag List"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand" />
<StackLayout>
<IndicatorView x:Name="snagListIndicator"
Margin="0,10,0,0"
IndicatorColor="LightGray"
SelectedIndicatorColor="LightGray"
IndicatorSize="6" />
<RefreshView Command="{Binding RefreshCommand}"
IsRefreshing="{Binding IsBusy, Mode=OneWay}"
Style="{StaticResource BaseRefreshView}">
<CarouselView x:Name="snagListCV"
Margin="10"
IndicatorView="snagListIndicator"
ItemsLayout="HorizontalList"
ItemsSource="{Binding SnagListPriorities.SnagListApps}"
CurrentItem="{Binding SnagListItem}"
Position="{Binding PositionIdx,Mode=OneWay}"
PositionChanged="CarouselView_PositionChanged"
Loop="False"
IsEnabled="{Binding IsNotBusy}">
<CarouselView.EmptyView>
<StackLayout Padding="12">
<Label Style="{StaticResource LabelMedium}"
HorizontalOptions="Center"
Text="{Binding EmptyMessage,Mode=TwoWay}" />
</StackLayout>
</CarouselView.EmptyView>
<CarouselView.ItemTemplate>
<DataTemplate>
<cells:SnagListCardX />
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</RefreshView>
</StackLayout>
<tabs:TabHostView x:Name="TabHost"
Margin="13,0,13,10"
BackgroundColor="{AppThemeBinding Dark={StaticResource Third},Light={StaticResource Fourth}}"
CornerRadius="30"
IsSegmented="True"
Orientation="Horizontal"
TabType="Fixed"
SelectedIndex="{Binding SelectedIndex,Mode=TwoWay}"
Shades="{StaticResource LightBottomShadow}">
<tabs:TabHostView.Behaviors>
<xct:EventToCommandBehavior EventName="SelectedTabIndexChanged"
Command="{Binding SelectedCommand}"
EventArgsConverter="{StaticResource TabSelectionChangedEventArgs}" />
</tabs:TabHostView.Behaviors>
<tabs:TabHostView.Tabs>
<tabs:BottomTabItem Style="{StaticResource BottomTabsMedium}"
Label="All">
<tabs:BottomTabItem.Badge>
<tabs:BadgeView Style="{StaticResource BadgeViewBase}"
BackgroundColor="{StaticResource All}"
TextColor="White"
Text="{Binding SnagListPriorities.All,Mode=TwoWay}" />
</tabs:BottomTabItem.Badge>
</tabs:BottomTabItem>
<tabs:BottomTabItem Style="{StaticResource BottomTabsMedium}"
Label="High"
StyleClass="">
<tabs:BottomTabItem.Badge>
<tabs:BadgeView Style="{StaticResource BadgeViewBase}"
BackgroundColor="{StaticResource High}"
TextColor="White"
Text="{Binding SnagListPriorities.High,Mode=OneWay}" />
</tabs:BottomTabItem.Badge>
</tabs:BottomTabItem>
<tabs:BottomTabItem Style="{StaticResource BottomTabsMedium}"
Label="Medium">
<tabs:BottomTabItem.Badge>
<tabs:BadgeView Style="{StaticResource BadgeViewBase}"
BackgroundColor="{StaticResource Medium}"
TextColor="Black"
Text="{Binding SnagListPriorities.Medium,Mode=TwoWay}" />
</tabs:BottomTabItem.Badge>
</tabs:BottomTabItem>
<tabs:BottomTabItem Style="{StaticResource BottomTabsMedium}"
Label="Low">
<tabs:BottomTabItem.Badge>
<tabs:BadgeView Style="{StaticResource BadgeViewBase}"
BackgroundColor="{StaticResource Low}"
TextColor="Black"
Text="{Binding SnagListPriorities.Low,Mode=TwoWay}" />
</tabs:BottomTabItem.Badge>
</tabs:BottomTabItem>
</tabs:TabHostView.Tabs>
</tabs:TabHostView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
And the view model
using AmsXamarin.Helpers;
using AmsXamarin.Models;
using AmsXamarin.Services;
using MvvmHelpers;
using MvvmHelpers.Commands;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Xamarin.Forms;
using Command = MvvmHelpers.Commands.Command;
namespace AmsXamarin.ViewModels
{
public class SnagListViewModel : BaseViewModel
{
readonly ISnagListService snagListService;
List<SnagListAppX> SnagListAppXs;
SnagListAppX snagListItem;
public SnagListAppX SnagListItem
{
get { return snagListItem; }
set
{
snagListItem = value;
OnPropertyChanged();
}
}
SnagListPriorities snagListPriorities;
public SnagListPriorities SnagListPriorities
{
get { return snagListPriorities; }
set
{
snagListPriorities = value;
OnPropertyChanged();
}
}
public AsyncCommand AddFaultCommand { get; }
public AsyncCommand AcceptCommand { get; }
public Command RefreshCommand { get; }
public Command SelectedCommand { get; }
public Command ShowMyJobsCommand { get; }
string emptyMessage;
public string EmptyMessage
{
get { return emptyMessage; }
set
{
emptyMessage = value;
OnPropertyChanged();
}
}
int positionIdx;
public int PositionIdx
{
get { return positionIdx; }
set
{
positionIdx = value;
OnPropertyChanged();
}
}
int selectedIndex;
public int SelectedIndex
{
get => selectedIndex;
set => SetProperty(ref selectedIndex, value);
}
string myJobsTitle = "My Jobs";
int staffId;
public string MyJobsTitle
{
get { return myJobsTitle; }
set
{
myJobsTitle = value;
OnPropertyChanged();
}
}
bool myJobsEnabled = true;
bool updateProperty = false;
public bool AcceptToolBar { get; set; }
public SnagListViewModel()
{
SnagListItem = new SnagListAppX();
SnagListPriorities = new SnagListPriorities()
{
SnagListApps = new ObservableRangeCollection<SnagListAppX>()
};
SnagListAppXs = new List<SnagListAppX>();
AddFaultCommand = new AsyncCommand(ShowAddSnagListItem);
AcceptCommand = new AsyncCommand(ShowModalAccept);
SelectedCommand = new Command(Selected);
RefreshCommand = new Command(Refresh);
staffId = 0;
ShowMyJobsCommand = new Command(ShowModalMyJobs);
snagListService = DependencyService.Get<ISnagListService>();
Device.BeginInvokeOnMainThread(async () =>
{
await GetSnagListItems();
});
}
async Task GetSnagListItems()
{
try
{
IsBusy = true;
EmptyMessage = "Loading...";
SnagListPriorities slp = await snagListService.GetSnagLists(false, true);
SnagListPriorities.SnagListApps.Clear();
SnagListPriorities = slp;
SnagListAppXs.Clear();
SnagListAppXs.AddRange(slp.SnagListApps);
EmptyMessage = SnagListAppXs.Count == 0 ? "Good Job! \r\n\r\nCurrently nothing to fix" : "";
IsBusy = false;
}
catch (Exception ex)
{
await Application.Current.MainPage.DisplayAlert("Error", ex.Message, "Ok");
}
}
void Selected()
{
//PositionIdx = 0;
//OnPropertyChanged(nameof(PositionIdx));
//FilterSnagList();
Refresh();
}
void FilterSnagList()
{
var allJobs = SnagListAppXs;
if (staffId != 0) allJobs = allJobs.Where(x => x.StaffId == staffId).ToList();
if (updateProperty) OnPropertyChanged(nameof(SnagListPriorities));
if (selectedIndex > 0) allJobs = allJobs.Where(sli => sli.Priority == selectedIndex).ToList();
SnagListPriorities.SnagListApps.Clear();
//SnagListPriorities.SnagListApps = new ObservableRangeCollection<SnagListAppX>(allJobs);
SnagListPriorities.SnagListApps.AddRange(allJobs);
//OnPropertyChanged(nameof(SnagListPriorities.SnagListApps));
updateProperty = false;
}
void ShowModalMyJobs()
{
staffId = myJobsEnabled ? int.Parse(Settings.StaffIdSetting) : 0;
MyJobsTitle = myJobsEnabled ? "All Jobs" : "My Jobs";
AcceptToolBar = !myJobsEnabled;
myJobsEnabled = !myJobsEnabled;
SelectedIndex = 0;
updateProperty = true;
}
void Refresh()
{
IsBusy = true;
var allJobs = SnagListAppXs.Where(s => s.StaffId == 115);
SnagListPriorities.SnagListApps.Clear();
SnagListPriorities.SnagListApps.AddRange(allJobs);
IsBusy = false;
}
}
}
looks a bit messy, but wanted to show, that I tried already a lot of things.
Last try was a simple RefreshView.
It works as long as the itemsSource is not changing. Once it changes and the first card is not shown, it crashes.
Any ideas? Many thanks

How can I put only English numbers in keyborard Xamarin.forms

My app has entry , when clicked it shows Numeric keyboard , the problem is if I put arabic numbers it doesn't calculate but close the app
is it possible to put only english number or how can I support arabic numbers ,
this is XAML file
<ContentPage.Content>
<AbsoluteLayout >
<!-- Text Box 1 -->
<StackLayout AbsoluteLayout.LayoutBounds="0.8,0.01" AbsoluteLayout.LayoutFlags="PositionProportional" >
<Label Text="" FontSize="Medium" FontAttributes="Bold" TextColor="Black" x:Name="lblname2" HorizontalOptions="Center" />
<Entry x:Name="Entnum2" WidthRequest="100" HeightRequest="40" BackgroundColor="White" Keyboard="Numeric" MaxLength="3" HorizontalTextAlignment="Center"
Focused="Entnum2_Focused" TextColor="Black" FontSize="Medium" PropertyChanged="Entnum2_PropertyChanged" />
</StackLayout>
<!-- Text Box 1 -->
<StackLayout AbsoluteLayout.LayoutBounds="0.2,0.01" AbsoluteLayout.LayoutFlags="PositionProportional">
<Label Text="" FontSize="Medium" FontAttributes="Bold" TextColor="Black" x:Name="lblname1" HorizontalOptions="Center" />
<Entry x:Name="Entnum1" WidthRequest="100" HeightRequest="40" BackgroundColor="White" Keyboard="Numeric" MaxLength="3" HorizontalTextAlignment="Center"
Focused="Entnum1_Focused" TextColor="Black" FontSize="Medium" />
</StackLayout>
<!-- view Editors -->
<Frame BackgroundColor="White" AbsoluteLayout.LayoutBounds="0.5,0.94,0.95,0.6" CornerRadius="15" AbsoluteLayout.LayoutFlags="All">
<ScrollView x:Name="scrollView" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!--<Editor Text="0" FontAttributes="Bold" TextColor="Black" FontSize="Medium" WidthRequest="100" x:Name="num1" Grid.Column="0" HorizontalOptions="Center" IsReadOnly="True" />-->
<Label Text="" FontAttributes="Bold" TextColor="Black" FontSize="25" WidthRequest="100" x:Name="num1" Grid.Column="0" HorizontalOptions="Center" />
<Image Source="linev.png" Grid.Column="1" Opacity="0.3"/>
<Label Text="" FontAttributes="Bold" TextColor="Black" FontSize="25" WidthRequest="100" x:Name="num2" Grid.Column="2" HorizontalOptions="Center" />
</Grid>
</ScrollView>
</Frame>
<!-- view Buttons -->
<StackLayout Orientation="Horizontal" AbsoluteLayout.LayoutBounds="0.5,0.14,0.95,0.09" AbsoluteLayout.LayoutFlags="All" >
<Button TextColor="#1C84D3" Text="تراجع" x:Name="btnBack" Clicked="btnBack_Clicked" HorizontalOptions="CenterAndExpand" BackgroundColor="White" CornerRadius="15" HeightRequest="70"
WidthRequest="70" FontSize="20" />
<Button TextColor="#1C84D3" Text="سجل" Clicked="btnRegister_Clicked" HorizontalOptions="CenterAndExpand" BackgroundColor="White" FontSize="20" CornerRadius="15" HeightRequest="70"
WidthRequest="70" />
</StackLayout>
<controls:AdControlView AbsoluteLayout.LayoutBounds="0.5,0.26,0.95,0.14" AbsoluteLayout.LayoutFlags="All"
AdUnitId="{Static local:Constants.AdUnitIdTest}"/>
</AbsoluteLayout>
</ContentPage.Content>
This is the XAML.cs
int SUM1 = 0;
// SUM2 لتخزين النتيجة الثانية
int SUM2 = 0;
// DisplayPromptAsync تخزين حالة الاشعار
string action;
// لتبديل بين entrys
int tap = 1;
// عدد الاعبين
int playercount = 1;
int count = 0;
bool scroll = false;
public Blootrecord(bool newplay)
{
InitializeComponent();
if (newplay)
{
DisplayPrompt(lblname1, "اسم فريقهم");
DisplayPrompt(lblname2, "اسم فريقنا?");
}
else
{
// اذا مالنت الثيمة ب False هذا يعني انه يريد الرجوع لاخر لعية
// هذه اسطر لجلب اخر قيم تم تخزينها
lblname1.Text = Preferences.Get("lblname1", "");
lblname2.Text = Preferences.Get("lblname2", "");
num1.Text = Preferences.Get("num1", "");
num2.Text = Preferences.Get("num2", "");
SUM1 = Convert.ToInt32(Preferences.Get("SUM1", "0"));
SUM2 = Convert.ToInt32(Preferences.Get("SUM2", "0"));
count = Convert.ToInt32(Preferences.Get("count", "0"));
}
scrollView.HeightRequest = num1.HeightRequest;
}
/// <summary>
/// هذه دالة لعررض الاشعار
/// </summary>
/// <param name="label"></param>
/// /// <param name="label2"></param>
/// <param name="str"></param>
async void DisplayPrompt(Label label, string str)
{
var s = await DisplayPromptAsync("Alert", str);
if (string.IsNullOrEmpty(s))
label.Text = "فريق" + playercount++;
else
label.Text = s;
}
/// <summary>
/// زر سجل
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
///
private async void btnRegister_Clicked(object sender, EventArgs e)
{
try
{
scrollView.HeightRequest = num1.HeightRequest;
scroll = false;
// اضافة سط في Editors مع القيمه المدخله
num1.Text += "\n" + Entnum1.Text;
num2.Text += "\n" + Entnum2.Text;
//اذا كان الentry فارغ يبدل القيمه ب صفر
if (string.IsNullOrEmpty(Entnum1.Text))
{
num1.Text += "0";
}
if (string.IsNullOrEmpty(Entnum2.Text))
{
num2.Text += "0";
}
//تحويل القيمه الي عدد صحيح وجمعها ع اخر قميه
SUM1 += int.Parse(num1.Text.Substring(num1.Text.LastIndexOf("\n") + 1));
SUM2 += int.Parse(num2.Text.Substring(num2.Text.LastIndexOf("\n") + 1));
// اذا كانت القيمه اقل من 152 يتم اضافة سطر ثم خط ثم قيمه الجمع في كل Editor
if (SUM1 < 152 && SUM2 < 152)
{
num1.Text += "\n" + "------";
num2.Text += "\n" + "------";
num1.Text += "\n" + SUM1;
num2.Text += "\n" + SUM2;
}
else
{
// يتم عرض اكير قيمه مع اكبر فائز
if (SUM1 > SUM2)
{
action = await DisplayActionSheet(" هاردلك الفوز لهم " + SUM1 + " ", "اغلاق", "لعبة جديدة");
}
else if (SUM1 < SUM2)
{
action = await DisplayActionSheet(" مبروك الفوز لنا" + SUM2 + "", "اغلاق", "لعبة جديدة");
}
else
{
action = await DisplayActionSheet("تعادل", "اغلاق", "لعبة جديدة");
}
// اذا قمت بأختيار لعبة جديدة
if (action == "لعبة جديدة")
{
// يحذف جميع القيم ولاكن يبقي اسم العبين
num1.Text = num2.Text = "0";
Entnum1.Text = Entnum2.Text = null;
SUM1 = SUM2 = 0;
await scrollView.ScrollToAsync(num1, ScrollToPosition.Start, true);
count = 0;
scroll = true;
}
}
Entnum1.Text = Entnum2.Text = null;
// store data
// تخزين البيانات في كل مره
Preferences.Set("lblname1", lblname1.Text);
Preferences.Set("lblname2", lblname2.Text);
Preferences.Set("num1", num1.Text);
Preferences.Set("num2", num2.Text);
Preferences.Set("SUM1", SUM1.ToString());
Preferences.Set("SUM2", SUM2.ToString());
count++;
if (count >= 5 && count <= 7 && !scroll)
{
await scrollView.ScrollToAsync(num1, ScrollToPosition.Center, true);
}
else if (count > 7 && !scroll)
{
await scrollView.ScrollToAsync(num1, ScrollToPosition.End, true);
}
}
catch (Exception ex)
{
// في حالة وجود خطأ غير متوقع
await DisplayAlert("Opps!", ex.Message, "Ok");
await Navigation.PopAsync();
}
}
void btnBack_Clicked(System.Object sender, System.EventArgs e)
{
try
{
if (num1.Text != "0" && num2.Text != "0")
{
// يتم اذالة ثلاث اسطر وطرح قيمة السطر الثالث من المجموع الكلي ثم ازالة السطر الثالث
// editor number one
num1.Text = num1.Text.Remove(num1.Text.LastIndexOf("\n"));
num1.Text = num1.Text.Remove(num1.Text.LastIndexOf("\n"));
SUM1 -= int.Parse(num1.Text.Substring(num1.Text.LastIndexOf("\n") + 1));
num1.Text = num1.Text.Remove(num1.Text.LastIndexOf("\n"));
// editor number two
num2.Text = num2.Text.Remove(num2.Text.LastIndexOf("\n"));
num2.Text = num2.Text.Remove(num2.Text.LastIndexOf("\n"));
SUM2 -= int.Parse(num2.Text.Substring(num2.Text.LastIndexOf("\n") + 1));
num2.Text = num2.Text.Remove(num2.Text.LastIndexOf("\n"));
}
}
catch (Exception ex)
{
DisplayAlert("Opps!", ex.Message, "Ok");
}
}
private void Entnum1_Focused(object sender, FocusEventArgs e)
{
tap = 1;
}
private void Entnum2_Focused(object sender, FocusEventArgs e)
{
tap = 2;
}
private void Entnum2_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
// في حالة اختيار Closr
if (action == "اغلاق")
{
// حزف جميع القيم المخزنه
Preferences.Clear();
// الرجوع الي الصفحة الاولة
Navigation.PopAsync();
}
}
}
}
This is an example of error , it calculates only English number
once I put Arabic Number it colses the app
Thank you
Arabic numbers are treated as char not numbers by the compiler if you want to use arabic number you have to manually map them with a case statement for example or a dictionary. if you parse them as an int an exception will be thrown.
problem fixed by this way
public int ArabicNumber (string unicode )
{
var str = unicode.Replace('\u0660', '0')
.Replace('0','0')
.Replace('\u0661', '1')
.Replace('\u0662', '2')
.Replace('\u0663', '3')
.Replace('\u0664', '4')
.Replace('\u0665', '5')
.Replace('\u0666', '6')
.Replace('\u0667', '7')
.Replace('\u0668', '8')
.Replace('\u0669', '9');
return int.Parse(str);
}

Animate labels for 20 seconds

I have 3 labels binded like following
<StackLayout>
<Label Padding="1" Text="VRN" FontSize="25" TextColor="Black" VerticalOptions="Center" HorizontalTextAlignment="Center"/>
<Label Padding="1" Text="{Binding VRN}" TextColor="#ba000d" FontSize="100" FontAttributes="Bold" VerticalOptions="Center" HorizontalTextAlignment="Center"/>
<Label Padding="1" Text="Make" FontSize="25" TextColor="Black" VerticalOptions="Center" HorizontalTextAlignment="Center"/>
<Label Text="{Binding Make}" TextColor="#ba000d" FontSize="100" FontAttributes="Bold" VerticalOptions="Center" HorizontalTextAlignment="Center"/>
<Label Text="{Binding Model}" TextColor="#ba000d" FontSize="30" FontAttributes="Bold" VerticalOptions="Center" HorizontalTextAlignment="Center"/>
</StackLayout>
Binding is done in ItemModel like following
string _vrn = "";
public string VRN
{
protected set
{
if (_vrn != value)
{
_vrn = value;
OnPropertyChanged("VRN");
}
}
get { return _vrn ; }
}
string _make= "";
public string Make
{
protected set
{
if (_make!= value)
{
_make= value;
OnPropertyChanged("Make");
}
}
get { return _make; }
}
string _model = "";
public string Model
{
protected set
{
if (_model != value)
{
_model = value;
OnPropertyChanged("Model");
}
}
get { return _model ; }
}
hubConnection.On<string>("NewItem", (item) =>
{
MainThread.BeginInvokeOnMainThread(async () =>
{
Item newItem = JsonConvert.DeserializeObject<Item>(item);
VRN= newItem.VRN;
Make= newItem.Make;
Model= newItem.Model;
}
}
Above code will set the labels with value of last item inserted. Up to here done.
I want to animate(Blink) the 3 labels for 20 seconds whenever new item is added to Item ObservableCollection(I am using SignalR to insert data)
I already have a class which i am using it with CollectionView for another scenario.Is there any way i can use the following class to animate Labels or is there any other easy way?
public class BlinkTriggerAction : TriggerAction<VisualElement>
{
protected async override void Invoke(VisualElement sender)
{
var parentAnimation = new Animation();
var fadeOutAnimation = new Animation(d => sender.Opacity = d, 1, 0, Easing.Linear);
var fadeInAnimation = new Animation(d => sender.Opacity = d, 0, 1, Easing.Linear);
parentAnimation.Add(0, 0.5, fadeOutAnimation);
parentAnimation.Add(0.5, 1, fadeInAnimation);
parentAnimation.Add(0, 0.5, fadeOutAnimation);
parentAnimation.Add(0.5, 1, fadeInAnimation);
parentAnimation.Add(0, 0.5, fadeOutAnimation);
parentAnimation.Add(0.5, 1, fadeInAnimation);
parentAnimation.Add(0, 0.5, fadeOutAnimation);
parentAnimation.Add(0.5, 1, fadeInAnimation);
parentAnimation.Commit(sender, "BlinkingVisualElement", 16, 800, repeat: () => true);
await Task.Delay(20000);
parentAnimation.Add(0, 0.5, fadeOutAnimation);
parentAnimation.Add(0.5, 1, fadeInAnimation);
sender.AbortAnimation("BlinkingVisualElement");
}
}
If you are looking for reusability I would suggest using behaviours instead of Triggers, as it lets you add it under the styles which Triggers don't.
Your BlinkTriggerBehavior would be something like this:
Note: I am using VisualElement here, you can use anything in future e.g Button, Label, Entry etc.
public class BlinkTriggerBehavior: Behavior<VisualElement>
{
protected override void OnAttachedTo(VisualElement bindable)
{
base.OnAttachedTo(bindable);
bindable.PropertyChanged += Animate; // binding property changed event
}
private async void Animate(object obj, PropertyChangedEventArgs e)
{
// your animation code gets fired everytime any of your Label
// property changes or any VisualElement which uses this behavior.
// If you wish you can use whatever property name you wish here or keep your
// animation code as is.
if (e.PropertyName == "Text")
{
//Your animation code
}
}
protected override void OnDetachingFrom(VisualElement bindable)
{
base.OnDetachingFrom(bindable);
bindable.PropertyChanged -= Animate;
}
}
In your MainPage.xaml, contentpage resource you can add the following:
<Style TargetType="Label">
<Style.Behaviors>
<views:BlinkTriggerBehavior />
</Style.Behaviors>
</Style>
... any other Target type Like you mentioned CollectionView ViewCell
If you want to make the animation for the label, you could download the source file from the link below:
https://learn.microsoft.com/en-us/samples/xamarin/xamarin-forms-samples/userinterface-animation-basic/
Change the xaml in RotateAnimationPage like below.
<StackLayout Margin="0,20,0,0">
<!--<Image x:Name="image" Source="monkey.png" VerticalOptions="CenterAndExpand" />-->
<Label
x:Name="image"
BackgroundColor="Accent"
HorizontalOptions="Center"
Text="Hello"
VerticalOptions="CenterAndExpand" />
<Button
x:Name="startButton"
Clicked="OnStartAnimationButtonClicked"
Text="Start Animation"
VerticalOptions="EndAndExpand" />
<Button
x:Name="cancelButton"
Clicked="OnCancelAnimationButtonClicked"
IsEnabled="false"
Text="Cancel Animation"
VerticalOptions="EndAndExpand" />
</StackLayout>
Screenshot:
And if you want to animate labels for 20 seconds, you could set the RotateTo length which to animate the transition to 20000. The screenshot set with 2000.
await image.RotateTo(360, 20000);

xamarin automatically adjust webview height

How to configure Xamarin Webview to display an automatic height according to html content?
I am developing a news app in Xamarin and I have this problem, because the webview forces me to inform the height and the width to display the information and as my content is dynamic, (always changes) ends up being an empty space on screen!
Sorry for english, I used google translate!
Thanks!
Code: PostView.cs
namespace AppNewsPlay.Views
{
public partial class PostView : TabbedPage
{
private int object_id;
// Criando a Listagem de Ultimas Noticias Playstation
List<PostViewModels> UPost;
public TabbedPage Detail { get; private set; }
public PostView(int object_id)
{
this.object_id = object_id;
UPost = new List<PostViewModels>();
ObterPost();
InitializeComponent();
}
private async void ObterPost()
{
var resp = string.Empty;
try
{
var uri = new HttpClient()
{
BaseAddress = new Uri("http://api.newsplay.com.br")
};
var url = "/api/post/" + this.object_id;
var result = await uri.GetAsync(url);
if (!result.IsSuccessStatusCode)
{
await DisplayAlert("Erro de Conexão", "Não foi possível obter as notícias do servidor, Tente novamente mais tarde!", "OK");
return;
}
resp = await result.Content.ReadAsStringAsync();
}
catch (Exception ex)
{
await DisplayAlert("Erro de Conexão com o Servidor", ex.Message, "OK");
return;
}
// transformando o retorno em objeto através do json e deserealize e retornando em lista
var UPost = JsonConvert.DeserializeObject<List<PostViewModels>>(resp);
var browser = new WebView();
// var htmlsource = new UrlWebViewSource();
foreach (var item in UPost)
{
var html = item.Guid;
browser.Source = html;
}
// Adicionando os itens ao ListView na Home.xaml - Aba Playstation*/
PostViewList.ItemsSource = UPost;
// ProgressLoader.IsRunning = false;
}
Code: PostView.xaml
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="AppNewsPlay.Views.PostView"
Title="Voltar"
Icon=""
BarBackgroundColor="#1c9e33"
>
<TabbedPage.Children>
<ContentPage Title="Notícia" Icon="ic_filter_list_black_24dp.png">
<ContentPage.Content >
<StackLayout
Spacing="20">
<ListView x:Name="PostViewList"
HasUnevenRows="True"
SeparatorColor="White"
SeparatorVisibility="Default"
>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout
Padding="20"
Orientation="Vertical"
>
<Label x:Name="Post_title" Text="{ Binding Post_title }"
FontSize="20"
FontAttributes="Bold"
HorizontalTextAlignment="Center"
/>
<Label x:Name="Post_ad" Text="{Binding Post_ad}"
FontSize="12"
HorizontalTextAlignment="Center"
/>
<WebView HorizontalOptions= "FillAndExpand"
VerticalOptions="FillAndExpand"
HeightRequest="3500"
WidthRequest="650"
x:Name="browser"
Source="{Binding Guid}"
>
</WebView>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
</TabbedPage.Children>
</TabbedPage>

Xamarin Forms - Thread Efficiency

I am developing a Xamarin (PCL) cross platform app that i am currently testing on my Android Physical devices and Emulators. The app runs perfectly on the high-end phones, but "crashes unexpectedly" on the Samsung S4 and such low-end phones. It crashes only after i perform multiple activities and tasks.
I am assuming that has something to do with the task-thread-capacity of these phones. If i am right in that regard, how am i supposed to make my app such that it works smoothly and error free on all phones?
Edit - The error says "The app has closed unexpectedly". This error doesn't appear on a specific line because it has nothing to do with the code. It breaks only on certain "older" phones when many activities are performed. Example of activities include, Add data to database, updating/deleting them, moving from one activity to another, showing calendars and pie-charts from user entered data.
Edit 2 -Some of the Code that deals with images:
Xaml:
<ScrollView HorizontalOptions="Fill" Orientation="Horizontal">
<StackLayout Orientation="Vertical" BackgroundColor="GhostWhite" >
<StackLayout Orientation="Horizontal" BackgroundColor="GhostWhite" >
<Button HeightRequest="50" BackgroundColor="GhostWhite" WidthRequest="50" Command="{Binding Button_Clicked_Food}" CommandParameter="dairy" Image="{Binding Dairy_Image}"/>
<Button HeightRequest="50" BackgroundColor="GhostWhite" WidthRequest="50" Command="{Binding Button_Clicked_Food}" CommandParameter="alcohol" Image="{Binding Alcohol_Image}"/>
<Button HeightRequest="50" BackgroundColor="GhostWhite" WidthRequest="50" Command="{Binding Button_Clicked_Food}" CommandParameter="eggs" Image="{Binding Egg_Image}"/>
<Button HeightRequest="50" BackgroundColor="GhostWhite" WidthRequest="50" Command="{Binding Button_Clicked_Food}" CommandParameter="fastfood" Image="{Binding Fastfood_Image}"/>
<Button HeightRequest="50" BackgroundColor="GhostWhite" WidthRequest="50" Command="{Binding Button_Clicked_Food}" CommandParameter="fish" Image="{Binding Fish_Image}"/>
<Button HeightRequest="50" BackgroundColor="GhostWhite" WidthRequest="50" Command="{Binding Button_Clicked_Food}" CommandParameter="fruit" Image="{Binding Fruit_Image}"/>
<Button HeightRequest="50" BackgroundColor="GhostWhite" WidthRequest="50" Command="{Binding Button_Clicked_Food}" CommandParameter="grain" Image="{Binding Grain_Image}"/>
<Button HeightRequest="50" BackgroundColor="GhostWhite" WidthRequest="50" Command="{Binding Button_Clicked_Food}" CommandParameter="legume" Image="{Binding Legume_Image}"/>
</StackLayout>
<StackLayout Orientation="Horizontal" BackgroundColor="GhostWhite" >
<Button HeightRequest="50" BackgroundColor="GhostWhite" WidthRequest="50" Command="{Binding Button_Clicked_Food}" CommandParameter="meat" Image="{Binding Meat_Image}"/>
<Button HeightRequest="50" BackgroundColor="GhostWhite" WidthRequest="50" Command="{Binding Button_Clicked_Food}" CommandParameter="munchies" Image="{Binding Munchies_Image}"/>
<Button HeightRequest="50" BackgroundColor="GhostWhite" WidthRequest="50" Command="{Binding Button_Clicked_Food}" CommandParameter="nuts" Image="{Binding Nut_Image}"/>
<Button HeightRequest="50" BackgroundColor="GhostWhite" WidthRequest="50" Command="{Binding Button_Clicked_Food}" CommandParameter="potato" Image="{Binding Potato_Image}"/>
<Button HeightRequest="50" BackgroundColor="GhostWhite" WidthRequest="50" Command="{Binding Button_Clicked_Food}" CommandParameter="soda" Image="{Binding Soda_Image}"/>
<Button HeightRequest="50" BackgroundColor="GhostWhite" WidthRequest="50" Command="{Binding Button_Clicked_Food}" CommandParameter="sweets" Image="{Binding Sweet_Image}"/>
<Button HeightRequest="50" BackgroundColor="GhostWhite" WidthRequest="50" Command="{Binding Button_Clicked_Food}" CommandParameter="vegetables" Image="{Binding Vegetable_Image}"/>
</StackLayout>
</StackLayout>
.CS:
public UserMealINC_vm(User_Profiles up, DateTime day)
{
try
{
Day = day;
User_pro = up;
Bool_Food_Type = false;
Food_Name = "";
Type = "";
Food_Weight = "0";
Selected_Food = new List<string>();
//All meal item are first initialized with the non-coloured images
Dairy_Image = "drawable/dairy.png";
Alcohol_Image = "drawable/alcohol.png";
Egg_Image = "drawable/eggs.png";
Fastfood_Image = "drawable/fastfood.png";
Fish_Image = "drawable/fish.png";
Fruit_Image = "drawable/fruit.png";
Grain_Image = "drawable/grain.png";
Legume_Image = "drawable/legume.png";
Meat_Image = "drawable/meat.png";
Munchies_Image = "drawable/munchies.png";
Nut_Image = "drawable/nuts.png";
Potato_Image = "drawable/potato.png";
Soda_Image = "drawable/soda.png";
Sweet_Image = "drawable/sweets.png";
Vegetable_Image = "drawable/vegetables.png";
this.Button_Clicked_Food = new Command<string>((key) =>
{
//Change the item selected from color to non-color, or vice-versa
if (Selected_Food.Contains(key))
{
if (key == "dairy")
{
Dairy_Image = "drawable/dairy.png";
}
else if (key == "alcohol")
{
Alcohol_Image = "drawable/alcohol.png";
}
else if (key == "eggs")
{
Egg_Image = "drawable/eggs.png";
}
else if (key == "fastfood")
{
Fastfood_Image = "drawable/fastfood.png";
}
else if (key == "fish")
{
Fish_Image = "drawable/fish.png";
}
else if (key == "fruit")
{
Fruit_Image = "drawable/fruit.png";
}
else if (key == "grain")
{
Grain_Image = "drawable/grain.png";
}
else if (key == "legume")
{
Legume_Image = "drawable/legume.png";
}
else if (key == "meat")
{
Meat_Image = "drawable/meat.png";
}
else if (key == "munchies")
{
Munchies_Image = "drawable/munchies.png";
}
else if (key == "nuts")
{
Nut_Image = "drawable/nuts.png";
}
else if (key == "potato")
{
Potato_Image = "drawable/potato.png";
}
else if (key == "soda")
{
Soda_Image = "drawable/soda.png";
}
else if (key == "sweets")
{
Sweet_Image = "drawable/sweets.png";
}
else if (key == "vegetables")
{
Vegetable_Image = "drawable/vegetables.png";
}
else
{
//Key out of bounds???
}
Selected_Food.Remove(key);
}
else
{
if (key == "dairy")
{
Dairy_Image = "drawable/dairy_color.png";
}
else if (key == "alcohol")
{
Alcohol_Image = "drawable/alcohol_color.png";
}
else if (key == "eggs")
{
Egg_Image = "drawable/eggs_color.png";
}
else if (key == "fastfood")
{
Fastfood_Image = "drawable/fastfood_color.png";
}
else if (key == "fish")
{
Fish_Image = "drawable/fish_color.png";
}
else if (key == "fruit")
{
Fruit_Image = "drawable/fruit_color.png";
}
else if (key == "grain")
{
Grain_Image = "drawable/grain_color.png";
}
else if (key == "legume")
{
Legume_Image = "drawable/legume_color.png";
}
else if (key == "meat")
{
Meat_Image = "drawable/meat_color.png";
}
else if (key == "munchies")
{
Munchies_Image = "drawable/munchies_color.png";
}
else if (key == "nuts")
{
Nut_Image = "drawable/nuts_color.png";
}
else if (key == "potato")
{
Potato_Image = "drawable/potato_color.png";
}
else if (key == "soda")
{
Soda_Image = "drawable/soda_color.png";
}
else if (key == "sweets")
{
Sweet_Image = "drawable/sweets_color.png";
}
else if (key == "vegetables")
{
Vegetable_Image = "drawable/vegetables_color.png";
}
else
{
//Key out of bounds???
}
Selected_Food.Add(key);
}
});
}
catch (Exception ex)
{
App.Current.MainPage.DisplayAlert("UserMealINC_vm 1!", ex.Message, "OK");
}
}
It turns out that the device memory was getting overflowed by all the multiple images i had in my App. (As suggested by #hvaughan3)
This link has the answer to it.
You basically just have to add these two lines in you Android Manifest (Under Application) -
android:hardwareAccelerated="false"
android:largeHeap="true"

Resources