editor length validation xamarin forms - validation

I would like to do some validation to this editor , for example "editor can not be empty write something". I could validate as input < 0 , however, I will need this validation in order to go to the next page . Any ideas ? Thanks.
this is my xaml.
<StackLayout Grid.Row="5" Grid.Column="0" Grid.ColumnSpan="3">
<Label Text="Description" FontSize="Medium" Style="{StaticResource LabelStyle}" />
<Editor x:Name="Description" FontSize="Medium" HeightRequest="120" TextChanged ="Handle_TextChanged" />
<Label x:Name ="Errorlabel"/>
</StackLayout>
cs:
async void Send_Activated(object sender, System.EventArgs e)
{
var editor = EDescription.Text;
if (string.IsNullOrWhiteSpace (editor))
{
Errorlabel.Text = "Plase add a description ";
ToolbarItems.Clear();
}
if (editor.Length >1)
{
await App.Navigator.PushAsync(new 2View());
}
}
toolbar :
<ContentPage.ToolbarItems>
<ToolbarItem x:Name = "anySend" Text="Send" Order="Primary" Activated="Send_Activated" />
</ContentPage.ToolbarItems>

a simple way to validate for non-null entries:
if (string.IsNullOrEmpty(Description.Text)) {
DisplayAlert("Error","Please enter a description", "OK");
} else {
Navigation.PushAsync(nextPage);
}
Xamarin also has an extensive writeup on doing Validation in MVVM

Related

i want to pass a parameter in a xaml button

hello i want to pass the Label with the button in xaml
its a list view and each row has her own Label and i want update each row by the label
<Label Grid.Column="2"
Grid.Row="1"
Text="{Binding Label}"
FontSize="20"
TextColor="Black"
Margin="0,10,0,0"
FontFamily="{StaticResource font}"
HorizontalOptions="Start"
VerticalOptions="Center"/>
<ImageButton Grid.Column="2"
Grid.Row="0"
HorizontalOptions="End"
VerticalOptions="End"
Source="plus.png"
Margin="9"
clicked ="update"
BackgroundColor="Transparent"/>
and the function in the class
public void update (object sender , EventArgs e)
{
update by the Label
}
i know that's there is something with commands but i'm beginner and i don't know how to use it i tried this and i didn't work.
Command="{Binding Path=BindingContext.UpdateCommand, Source={x:Reference Name=listViewEvent}}"
CommandParameter="{Binding Label}"
and the function is this
UpdateCommand = new Command<string>(async (args) => {
String Label = args as string;
DisplayAlert("update", "update", "OK");
_ = Navigation.PushAsync(new AddReminder(Label));
});
and the alert didn't show
please i need help
you don't need to "pass" the Label
<ImageButton Grid.Column="2" Cilcked="update" ... />
protected void update(object sender, EventArgs a)
{
var btn = (ImageButton)sender;
// MyClassName should be the name of your model class
// this will get you the object referenced by the selected row
var item = (MyClassName)btn.BindingContext;
// then you can reference any property of item
// ie, item.Label, etc
}
<Label x:Name="myLabel"
Grid.Column="2"
Grid.Row="1"
Text="{Binding Label}"
FontSize="20"
TextColor="Black"
Margin="0,10,0,0"
FontFamily="{StaticResource font}"
HorizontalOptions="Start"
VerticalOptions="Center"/>
<ImageButton Grid.Column="2"
Grid.Row="0"
HorizontalOptions="End"
VerticalOptions="End"
Source="plus.png"
Margin="9"
clicked ="update"
BackgroundColor="Transparent"
CommandParameter={x:Reference myLabel}/>
And then in code behind you can get the label
protected void update(object sender, EventArgs a)
{
var btn = (ImageButton)sender;
var label = btn.CommandParameter as Xamarin.Forms.Label;
}

Gesture Recognizer go to detail

i have a page with Cards and once i tap on one i need to get detailed data. I have Gesture recognizer so i am able to navigate to he second page but with no details.
I have tried to add TapGesture in xaml but it didnt work.
This is my xaml
<grial:Repeater
Padding="0"
ItemsSource="{ Binding ListOfBestSellers }"
Orientation="Horizontal"
HeightRequest="200"
Spacing="0"
VerticalOptions="End"
ScrollBarVisibility="Never">
<grial:Repeater.ItemTemplate>
<DataTemplate >
<local:AvatArticleBrowserCardItemTemplate
Padding="10,0,5,5"
WidthRequest="150" >
</local:AvatArticleBrowserCardItemTemplate>
</DataTemplate>
</grial:Repeater.ItemTemplate>
</grial:Repeater>
and Template
<ContentView.Content>
<grial:CardView
VerticalOptions="Fill"
CornerRadius="5" x:Name="articleCard">
<grial:CardView.RowDefinitions>
<RowDefinition
Height="*" />
<RowDefinition
Height="Auto" />
</grial:CardView.RowDefinitions>
<!-- ARTICLE IMAGE -->
<ffimageloading:CachedImage
Grid.Row="0"
Margin="-14,0,-14,10"
Source="{ Binding BackgroundImage }"
Aspect="AspectFill" />
<Grid
Grid.Row="1"
VerticalOptions="End"
RowSpacing="10"
Padding="14,10">
<!-- TITLE -->
<Label
Grid.Row="0"
Text="{ Binding Title }"
FontSize="15"
Style="{ StaticResource LabelBoldStyle }"
TextColor="{ DynamicResource AccentColor }" />
<!-- CATEGORY -->
<Label
Grid.Row="1"
Text="{ Binding Section }"
FontSize="12"
VerticalOptions="Start" />
<!-- DATE -->
<Label
Grid.Row="1"
Text="{ Binding When }"
FontSize="12"
VerticalOptions="Start"
HorizontalOptions="End" />
</Grid>
</grial:CardView>
</ContentView.Content>
This is what i have
async void GoToCardDetail(object sender, EventArgs e)
{
if (LangUpLoggedUser.LoggedIn)
{
await Navigation.PushAsync(new MyArticle());
}
else
{
await Navigation.PushAsync(new Login());
}
}
private void CardDetail()
{
articleCard.GestureRecognizers.Clear();
TapGestureRecognizer gestureRecognizerArticleDetail = new TapGestureRecognizer();
gestureRecognizerArticleDetail.Tapped += GoToCardDetail;
articleCard.GestureRecognizers.Add(gestureRecognizerArticleDetail);
}
But its not giving me detailed data, on my list view from other page i have this
private async void ListView_ItemTapped(object sender, ItemTappedEventArgs e)
{
#if !NAVIGATION
var selectedItem = ((ListView) sender).SelectedItem;
var articlePage = new MyArticle(selectedItem as ArticleDetailData);
await Navigation.PushAsync(articlePage);
#endif
}
my MyArticle const
public MyArticles()
{
InitializeComponent();
BindingContext = new MyArticlesListViewModel(null);
}
/// <summary>
///
/// </summary>
/// <param name="articles"></param>
/// <param name="categoryName"></param>
public MyArticles(List<Article> articles, string categoryName)
{
_categoryName = categoryName;
InitializeComponent();
BindingContext = new MyArticlesListViewModel(articles);
}
And that works perfectly can zou please help me how to achieve the same result?
you need to pass the selected item to MyArticle's constructor
var card = (CardView) sender;
var item = (ArticleDetailData)card.BindingContext;
await Navigation.PushAsync(new MyArticle(item));

How to create listview navigation in shell tab bar using xamarin form cross platform?

Xamarin Forms Cross Platform.
1. I'm using Shell to create Tab Bar, one of the tab bar consist listview.
2. Each cell will navigate to the its details page.
My problem here:
Since I'm using Shell (new feature of xamarin 4.0), I've no idea how to make listview navigation page.
Appreciate those who know using shell navigation to enable my cells in listview able navigate to particular page.
<StackLayout Orientation="Vertical">
<Frame BackgroundColor="DarkOrange" HeightRequest="100" Margin="10,10,10,20" BorderColor="Black" HasShadow="True">
</Frame>
<ListView x:Name="ListView" SeparatorVisibility="Default" SeparatorColor="Red" IsPullToRefreshEnabled="True"
>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<Image Source="{Binding Icon}"/>
<Label Text="{Binding Name}" FontAttributes="Bold" VerticalTextAlignment="Center"
HorizontalOptions="StartAndExpand"/>
<Image Source="{Binding RightArrowIcon}" HorizontalOptions="End"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
async private void ListView_ItemSelected(object sender,
SelectedItemChangedEventArgs e)
{
if(e.SelectedItem != null)
{
var listview = e.SelectedItem as MeListView;
var name = listview.Name.ToString();
if (e.SelectedItem == null)
return;
ListView.SelectedItem = null; //clear the selected item when
back to the listview.
switch (name)
{
case "Payment Methods":
await Navigation.PushAsync(new PaymentPage(listview));
break;
case "Setting":
await Navigation.PushAsync(new SettingPage(listview));
break;
case "FAQ":
await Navigation.PushAsync(new FaqPage(listview));
break;
case "Terms & Conditions":
await Navigation.PushAsync(new TermsPage(listview));
break;
case "About us":
await Navigation.PushAsync(new AboutPage(listview));
break;
case "Contact us":
await Navigation.PushAsync(new ContactPage(listview));
break;
}
}
}
My problem here: Since I'm using Shell (new feature of xamarin 4.0), I've no idea how to make listview navigation page.
First add ItemSelected="OnItemSelected" to ListView in Xaml:
<ListView x:Name="ListView" SeparatorVisibility="Default" SeparatorColor="Red" IsPullToRefreshEnabled="True" ItemSelected="OnItemSelected">
<ListView.ItemTemplate>
//...
</ListView.ItemTemplate>
</ListView>
Then in OnItemSelected func, you can write your navigation function.In shell app, you also can use Navigation.PushAsync to navigat to next page. As follow:
void OnItemSelected(object sender, SelectedItemChangedEventArgs args)
{
var item = args.SelectedItem as Item;
if (item == null)
return;
switch (args.SelectedItemIndex)
{
case 0:
Console.WriteLine("Case 1");
Navigation.PushAsync(new PayMentPage());
break;
case 1:
Console.WriteLine("Case 2");
Navigation.PushAsync(new SettingPage());
break;
//...
default:
Console.WriteLine("Default case");
break;
}
}
In addition, shell app offer new way to navigate ( Shell.Current.GoToAsync ).To do this , you should register page first by Routes. As follow:
Register Page:
Routing.RegisterRoute("setting", typeof(SettingPage));
Perform navigation:
Shell.Current.GoToAsync("setting");
This is the easy way to use shell's navigation , there is other important points about Routes and Navigation .Here is the official document for reference.
===================================Update====================================
If want to navigate to detail page ,and the Tab bar is not visible, you sholud manually do that in Detail Page.As follow:
Shell.SetTabBarIsVisible(this, false);
There is no in-built mechanism for this. But it is fairly simple to implement.
You can either use ItemSelected OR ItemTapped event of ListView as follows:
<ListView x:Name="ListView" SeparatorVisibility="Default" SeparatorColor="Red" IsPullToRefreshEnabled="True" ItemTapped="OnListViewItemTapped">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<Image Source="{Binding Icon}"/>
<Label Text="{Binding Name}" FontAttributes="Bold" VerticalTextAlignment="Center"
HorizontalOptions="StartAndExpand"/>
<Image Source="{Binding RightArrowIcon}" HorizontalOptions="End"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
In code behind:
async void OnListViewItemTapped(object sender, ItemTappedEventArgs e)
{
await Shell.Current.Navigation.PushAsync(new DetailsPage());
}

How to display a ListView and Other Controls in a ScrollView?

I want to display a ListView and other controls inside a ScrollView. All is bound to a ViewModel. My attempts failed because it's not recommend to put a ListView inside a ScrollView. As I use a complex ViewCell DataTemplate, I did not consider to add my items in the code behind file as Buttons instead of a ListView.
Hope someone can show me a Xaml or CS pattern to achieve my goal.
Please only suggest a solution which works on iOS and Android!
Thanks
Eric
This is XAML code
<ScrollView Padding="2">
<StackLayout HorizontalOptions="FillAndExpand">
<Grid HorizontalOptions="FillAndExpand">
<StackLayout>
<ScrollView Orientation="Horizontal">
<ListView BackgroundColor="Transparent" ItemsSource="{Binding UsersList}" SeparatorVisibility="None" x:Name="YourListView" RowHeight="50">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout BackgroundColor="Transparent" Padding="5">
<Button Text="{Binding UserName}" WidthRequest="115" HorizontalOptions="FillAndExpand" TextColor="White" BackgroundColor="#4b76c4" FontAttributes="Bold" FontSize="20" FontFamily="Avenir Book"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ScrollView>
</StackLayout>
</Grid>
</StackLayout>
</ScrollView>
and .cs file you need set BindingContext
BindingContext = new YourViewModel();
Solution:
As Rodrigo E suggested I download the latest Xamarin Evolve App 2016. After digging through the code I adjusted/simplified the FeedPage.xaml in the solution to that:
<?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:XamarinEvolve.Clients.UI;assembly=XamarinEvolve.Clients.UI"
xmlns:pull="clr-namespace:Refractored.XamForms.PullToRefresh;assembly=Refractored.XamForms.PullToRefresh"
x:Class="XamarinEvolve.Clients.UI.FeedPage"
x:Name="FeedPage"
Title="Evolve Feed"
Icon="tab_feed.png"
BackgroundColor="{DynamicResource WindowBackgroundTable}">
<pull:PullToRefreshLayout
IsPullToRefreshEnabled="True"
RefreshCommand="{Binding RefreshCommand}"
IsRefreshing="{Binding IsBusy}">
<local:AlwaysScrollView
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<StackLayout>
<StackLayout Spacing="0">
<local:NonScrollableListView
x:Name="ListViewSessions"
ItemsSource="{Binding Sessions}">
<local:NonScrollableListView.RowHeight>
<OnPlatform x:TypeArguments="x:Int32" Android="50" iOS="50" WinPhone="50"/>
</local:NonScrollableListView.RowHeight>
<local:NonScrollableListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Button Text="{Binding Title}" BackgroundColor="Black" TextColor="Green" />
</ViewCell>
</DataTemplate>
</local:NonScrollableListView.ItemTemplate>
</local:NonScrollableListView>
</StackLayout>
<StackLayout Padding="0" Spacing="0" BackgroundColor="Green">
<Button Text="OTHER" BackgroundColor="Blue" TextColor="White" />
<Button Text="OTHER" BackgroundColor="Blue" TextColor="White" />
<Button Text="OTHER" BackgroundColor="Blue" TextColor="White" />
<Button Text="OTHER" BackgroundColor="Blue" TextColor="White" />
<Button Text="OTHER" BackgroundColor="Blue" TextColor="White" />
<Button Text="OTHER" BackgroundColor="Blue" TextColor="White" />
</StackLayout>
</StackLayout>
</local:AlwaysScrollView>
</pull:PullToRefreshLayout>
There are a few things to do:
In the FeedViewModel.cs I added that code for a quick test:
async Task ExecuteLoadSessionsCommandAsync()
{
if (LoadingSessions)
return;
LoadingSessions = true;
try
{
NoSessions = false;
Sessions.Clear();
OnPropertyChanged("Sessions");
#if DEBUG
await Task.Delay(1000);
#endif
var sessions = await StoreManager.SessionStore.GetNextSessions();
var testSessions = new List<Session>();
testSessions.Add(new Session
{
Title = "TEST"
});
testSessions.Add(new Session
{
Title = "TEST"
});
testSessions.Add(new Session
{
Title = "TEST"
});
sessions = testSessions;
if(sessions != null)
Sessions.AddRange(sessions);
NoSessions = Sessions.Count == 0;
}
catch(Exception ex)
{
ex.Data["method"] = "ExecuteLoadSessionsCommandAsync";
Logger.Report(ex);
NoSessions = true;
}
finally
{
LoadingSessions = false;
}
}
You have to reference the package Refractored.XamForms.PullToRefresh to get the Pull-to-Refresh behavor.
This is in that namespace referenced: xmlns:pull="clr-namespace:Refractored.XamForms.PullToRefresh;assembly=Refractored.XamForms.PullToRefresh"
You have to Copy the AlwaysScrollView , NonScrollableListView to your PCL library.
refercene it with: xmlns:local="clr-namespace:"
In your iOS Project add that custom ListView Renderer:
public class NonScrollableListViewRenderer : ListViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs e)
{
base.OnElementChanged(e);
if (Control != null)
Control.ScrollEnabled = false;
}
}
public class AlwaysScrollViewRenderer : ScrollViewRenderer
{
public static void Initialize()
{
var test = DateTime.UtcNow;
}
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
this.AlwaysBounceVertical = true;
}
}
See file: Renderer
Put that CollectionChanged Handler in your Code-behind file:
ViewModel.Sessions.CollectionChanged += (sender, e) =>
{
var adjust = Device.OS != TargetPlatform.Android ? 1 : -ViewModel.Sessions.Count + 1;
ListViewSessions.HeightRequest = (ViewModel.Sessions.Count * ListViewSessions.RowHeight) - adjust;
};
See File FeedPage.cs.xaml: FeedPage.cs.xaml

How to disable highlight on ListView in Xamarin.Forms

I'm working with Xamarin.Forms and XAML, and I'm trying to create an application that stores a list of products. I put my list of products in a ListView. This works fine. Here is my XAML:
<ListView x:Name="listSushi"
ItemsSource="{x:Static local:myListSushi.All}"
SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
RowHeight="{StaticResource rowHeight}"
>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout Padding="5, 5, 0, 5"
Orientation="Horizontal"
Spacing="15">
<StackLayout>
<Image Source="{Binding ImageSource}" />
</StackLayout>
<StackLayout Padding="0, 0, 0, 0"
VerticalOptions="Center"
HorizontalOptions="FillAndExpand">
<Label Text="{Binding Name}"
Font="Bold, Medium" />
<Label Text="{Binding Description}"
Font="Small"/>
</StackLayout>
<StackLayout Orientation="Horizontal"
Padding="0, 0, 10, 0">
<Button Text=" - "
HorizontalOptions="EndAndExpand"
VerticalOptions="FillAndExpand"
Command="{Binding DeleteSushiCommand}"
CommandParameter="{Binding Name}"
/>
<Label VerticalOptions="Center"
Text="{Binding Number,StringFormat='{0}'}"
TextColor="Black"/>
<Button Text=" + "
HorizontalOptions="EndAndExpand"
VerticalOptions="FillAndExpand"
Command="{Binding AddSushiCommand}"
CommandParameter="{Binding Name}"
/>
</StackLayout>
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
I've just the problem that if I click on a cell of my listView, the cell is highlight, and stay highlight. I've try to disable it with this code in the xaml.cs
listSushi.ItemSelected+= (object sender, SelectedItemChangedEventArgs e) => {
// don't do anything if we just de-selected the row
if (e.SelectedItem == null) return;
// do something with e.SelectedItem
((ListView)sender).SelectedItem = null; // de-select the row
};
But when I touch a cell, now my list is scrolling automatically. It's very strange.
Does anyone know if this is a bug, or know a fix, like if there is a property where I can disable the highlight?
You might try using the ItemTapped event instead, i.e.
listSushi.ItemTapped += (object sender, ItemTappedEventArgs e) => {
// don't do anything if we just de-selected the row.
if (e.Item == null) return;
// Optionally pause a bit to allow the preselect hint.
Task.Delay(500);
// Deselect the item.
if (sender is ListView lv) lv.SelectedItem = null;
// Do something with the selection.
...
};
I have tested this on a ListView (on an Android device) that has enough items to bring scrolling into the mix. I see no auto-scroll behavior, and your idea to set SelectedItem null to defeat the highlight works great.
Current we can set ListView.SelectionMode to None to do this.
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/listview/interactivity
I just found another method to disable the highlight effect. And i would like to share this with other users.
You can do it directly at xaml. But this method not only disable the highlight effect, it will also disable the click event.
You can set the IsEnabled attribute of ViewCell to false.
<ViewCell IsEnabled="false">
//Your Item Layout Coding
</ViewCell>
In addition, you can also disable/enable each item highlight effect by binding:
<ViewCell IsEnabled="{Binding IsHighlightEnabled}">
//Your Item Layout Coding
</ViewCell>
Hope that helps, thanks.
YourList.ItemSelected+=DeselectItem;
public void DeselectItem(object sender, EventArgs e)
{
((ListView)sender).SelectedItem = null;
}
This should be helpful for your scenario. #dpfauwadel
I am assuming you are using MVVM. In these cases I assign a null to the property after using it. In your viewmodel you seem to have a SelectedItem property since you are binding it to the SelectedItem property of the ListView. So I would do something like this:
private Product _selectedItem;
public Product SelectedItem
{
get
{
return _selectedItem;
}
set
{
_selectedItem = value;
//USE THE VALUE
_selectedItem = null;
NotifyPropertyChanged("SelectedItem");
}
}
On iOS mark's solution didn't solve it for me, I had to create a CustomRenderer for the list view and use that instead.
NonSelectableListView.cs (In your Forms Project)
using System;
using Xamarin.Forms;
namespace YourProject
{
public class NonSelectableListView : ListView
{
public NonSelectableListView()
{
}
}
}
NonSelectableListViewRenderer.cs (CustomRenderer in your iOS project)
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using YourProject.iOS;
using YourProject;
[assembly: ExportRenderer(typeof(NonSelectableListView), typeof(NonSelectableListViewRenderer))]
namespace YourProject.iOS
{
public class NonSelectableListViewRenderer : ListViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
// Unsubscribe from event handlers and cleanup any resources
}
if (e.NewElement != null)
{
// Configure the native control and subscribe to event handlers
Control.AllowsSelection = false;
}
}
}
}

Resources