Entry is in focus, soft keyboard is shown.
Clicking on another visual element (In this case, the Grid) causes entry to lose focus,
and the keyboard to hide:
<Entry x:Name="SearchBox"
Grid.Column="1"
Text="{Binding AddressSearchText}" />
<Grid Grid.Column="2">
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding ClearSearchCommand}" />
</Grid.GestureRecognizers>
<Image Source="{customControls:ImageMultiResource cross}"
Aspect="AspectFit"
HeightRequest="18"
WidthRequest="18"
VerticalOptions="Fill"
InputTransparent="True" />
</Grid>
I want the user to be able to click on the Grid button and have the Entry still in focus,
with the keyboard showing.
How can I make the Grid unfocusable, so it doesn't cause the Entry to lose focus?
You could set the Entry active in the command .
<TapGestureRecognizer Command="{Binding ClearSearchCommand}" CommandParameter="{Binding Source={x:Reference SearchBox}, Path=.}" />
ClearSearchCommand = new Command((arg)=> {
var entry = arg as Entry;
entry.Focus();
//...
});
Related
I work on the front end of our app, configuring the UI. Our app originally had a ListView using Xamarin Community Toolkit's EventToCommandBehavior with custom ViewCells to facilitate the search. We set up custom renderers to change the ViewCell's background color. However, when I moved over to the Mac, we discovered that none of that worked with iOS; the cell background would not change.
At this point, I switched to a CollectionView with a TapGestureRecognizer on the grid using VisualStateManager to change the background color. Since then, I can either get the grid selection to highlight without the command enabling our buttons or the command to fire which enables the buttons, but the grid selection will not highlight. Simply put, I either get the command or the event but have been unable to get them working together. This is also a problem on our store page; the IAP's never highlighted before the purchase confirmation popped up. We have been experiencing this issue from the start and never noticed.
Here is the relevant XAML:
<!--Faction Search Results-->
<Frame Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="6" BackgroundColor="Black" BorderColor="White" CornerRadius="5">
<CollectionView ItemsSource="{Binding FactionItems}"
BackgroundColor="Transparent">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid x:DataType="Data:Faction" BackgroundColor="Black">
<Grid.GestureRecognizers>
<TapGestureRecognizer
NumberOfTapsRequired="1"
Command="{Binding Source={RelativeSource AncestorType={x:Type local:FactionTopPageViewModel}}, Path=ItemTapped}"
CommandParameter="{Binding .}">
</TapGestureRecognizer>
</Grid.GestureRecognizers>
<Grid.RowDefinitions>
<RowDefinition Height="{markups:OnScreenSize DefaultSize='12', iPod='20', iPhoneSE='20', iPhoneXR='20', iPhoneX='20', iPhone13='25', iPhone7p='25', iPhone11pm='25', iPhone13pm='16',
iPadMini='35', iPad9p7='35', iPad='35', iPadAir='35', iPad11='35', iPad12p9='40', Nexus1='20', NexusR='25', Nexus7R='30', Pixel2R='25', Pixel3R='25', GalaxyS8='25', Nexus6P='25', Pixel3XL='25', PixelC='40'}" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Padding="10,5" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="4" Text="{Binding FactionName}" HorizontalOptions="Start" VerticalTextAlignment="End" FontAttributes="Bold"
FontSize="{markups:OnScreenSize DefaultSize='12', iPod='15', iPhoneSE='15', iPhoneXR='18', iPhoneX='19', iPhone13='19', iPhone7p='19', iPhone11pm='19', iPhone13pm='16',
iPadMini='30', iPad9p7='30', iPad='32', iPadAir='32', iPad11='34', iPad12p9='34', Nexus1='14', NexusR='14', Nexus7R='22', Pixel2R='20', Pixel3R='20', GalaxyS8='20', Nexus6P='18', Pixel3XL='18', PixelC='34'}" />
<Label Padding="0,5" Grid.Row="0" Grid.Column="4" Grid.ColumnSpan="2" Text="{Binding NumberMembersString}" HorizontalOptions="Center" VerticalTextAlignment="End" FontAttributes="Bold"
FontSize="{markups:OnScreenSize DefaultSize='12', iPod='15', iPhoneSE='15', iPhoneXR='18', iPhoneX='19', iPhone13='19', iPhone7p='19', iPhone11pm='19', iPhone13pm='16',
iPadMini='30', iPad9p7='30', iPad='32', iPadAir='32', iPad11='34', iPad12p9='34', Nexus1='14', NexusR='14', Nexus7R='22', Pixel2R='20', Pixel3R='20', GalaxyS8='20', Nexus6P='18', Pixel3XL='18', PixelC='34'}"/>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="CommonStates">
<VisualState Name="Normal"></VisualState>
<VisualState Name="Selected">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="#ae00ff"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
Relevant code from the ViewModel:
public Command<Faction> ItemTapped { get; }
public FactionTopPageViewModel()
{
ItemTapped = new Command<Faction>(OnItemSelected);
}
private void OnItemSelected(Faction faction)
{
if (faction == null)
{
SelectedItem = null;
DisableFactionButtons();
return;
}
EnableFactionButtons();
SelectedItem = faction;
}
This results in our buttons enabled at the bottom of the page, but the faction (essentially a team) is not being highlighted in the CollectionView, so the user does not receive confirmation of selecting the proper faction.
If I remove the tapgesture and work through the CollectionView commands setting the SelectionMode="Single", SelectionChangedCommand={Binding IsTapped}, and SelectionChangedCommandParameter={Binding .} then the selected Faction highlights without enabling any buttons. These issues are not platform-specific, like the ListView ViewCell background.
I have been working on this longer than I care to mention, as it seems like I have not wrapped my head around some relatively simple concept. Any help would be greatly appreciated, this issue is holding up the next release of our app.
I have a ListView with an ObservableCollection as the ItemsSource. Amongst others I have a CheckBox in the ListView with its IsChecked-Property bound to the collection (for simplicity I've just stated the CheckBox in the code below). Now I would like to implement EventToCommandBehavior from XCT to the CheckBox, though the Command won't fire. If I put the CheckBox outside of the ListView the EventToCommandBehavior fires though (of course without all the reference and source, just stating Command="{Binding ButtonLoeschenEnableDisableCommand})...
<ContentPage x:Name="ContentPageAnzeigenBearbeiten"
Title="Anzeigen & Bearbeiten">
<ContentPage.BindingContext>
<vm:LesezeichenViewModel/>
</ContentPage.BindingContext>-->
<Grid >
<ListView x:Name="listViewBookmarks"
HasUnevenRows="True"
ItemsSource="{Binding Bookmarks}"
CachingStrategy="RecycleElement">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay}" HorizontalOptions="End">
<CheckBox.Behaviors>
<xct:EventToCommandBehavior EventName="CheckedChanged"
Command="{Binding LesezeichenViewModel.ButtonLoeschenEnableDisableCommand, Source={x:Reference Name=ContentPageAnzeigenBearbeiten}, Mode=TwoWay}"/>
</CheckBox.Behaviors>
</CheckBox>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</ContentPage >
I am using Rg.Plugins.Popup plugin in my xamarin forms app. It is a nice plugin for modal dialogs. However, I am looking to dismiss the dialog when user scrolls down. (Most dialogs in iOS has this behavior of closing with scrolling down).
XAML inside Popup page.
Option 1
<pages:PopupPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:pages="clr-namespace:Rg.Plugins.Popup.Pages;assembly=Rg.Plugins.Popup"
HasSystemPadding="True"
CloseWhenBackgroundIsClicked="False"
x:Name="MyPage"
x:Class="wQuran.Views.Today.PrayerTimesSettingsPopupPage">
<Frame Style="{DynamicResource PopupFrame}" VerticalOptions="FillAndExpand" IsClippedToBounds="True">
<Grid RowDefinitions="Auto,*" Style="{DynamicResource BaseGrid}">
<BoxView Grid.Row="0" Style="{DynamicResource PopupTitleBoxView}"/>
<Grid Grid.Row="0" ColumnDefinitions="*,30" HeightRequest="40" Padding="10">
<Label Grid.Column="0" Text="{Binding Title}" Style="{DynamicResource PopupTitleLabel}"/>
<ImageButton Grid.Column="1" Style="{DynamicResource DialogCloseImageButton}" Command="{Binding CloseDialogCommand}"/>
</Grid>
</Grid>
</Frame>
</pages:PopupPage>
Option 2.
Updated XAML and added the Frame inside ScrollView
<ScrollView Scrolled="ScrollView_Scrolled">
....
</ScrollView>
private void ScrollView_Scrolled(object sender, Xamarin.Forms.ScrolledEventArgs e)
{
if (e.ScrollY > 100)
{
itemViewModel.CloseDialogCommand.Execute(null);
}
}
In option 1 I don't have the scroll, so the plug in works with default behavior, but I have no way to close the dialog in scroll.
In option 2, I added the frame inside the scrollview to check for Y scroll and dismiss the dialog. The Scrolled event never fires. Additionally, I cannot close the dialog when clicking outside the modal.
After all, my question is how to dismiss the dialog while scrolling down?
After all, my question is how to dismiss the dialog while scrolling down?
I guess that you want to close PopupPage when ScrollView scroll ending. If yes, please take a look the following code:
<pages:PopupPage
x:Class="FormsSample.simplecontrol.Page16"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:pages="clr-namespace:Rg.Plugins.Popup.Pages;assembly=Rg.Plugins.Popup">
<StackLayout
Padding="20,0"
HorizontalOptions="FillAndExpand"
VerticalOptions="Center">
<Frame
Padding="0"
BackgroundColor="CadetBlue"
CornerRadius="10"
HeightRequest="100">
<ScrollView Scrolled="ScrollView_Scrolled">
<StackLayout Padding="10">
<Label
FontSize="20"
HorizontalOptions="Center"
Text="First Popup Page"
TextColor="Black" />
<Label Text="Hello Xamarin Guys" TextColor="Red" />
<Label Text="This is Very Awesome Popup Plugins For Xamarin forms" TextColor="LightBlue" />
<Button Text="Close" TextColor="Black" />
<Image Source="a11.jpg" />
</StackLayout>
</ScrollView>
</Frame>
</StackLayout></pages:PopupPage>
private async void ScrollView_Scrolled(object sender, ScrolledEventArgs e)
{
ScrollView scrollView = sender as ScrollView;
double scrollingSpace = scrollView.ContentSize.Height - scrollView.Height;
if (scrollingSpace <= e.ScrollY) // Touched bottom
// Do the things you want to do
await PopupNavigation.Instance.PopAsync();
}
I am trying to achieve the effect, cross-platform(ios, android and uwp), as shown in the image below:
Clicking "More" normally would open a page, as normal behaviour for a tab bar item. Not sure how to override that behaviour and reveal the sliding master page instead. To the left of the "More" tab bar item, theres another tab bar item, when clicked it refreshes the data on (or reloads) the MainPage.
SettingsPage.xaml (master page, the sliding settings page)
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MyProject.Classes"
xmlns:views="clr-namespace:MyProject.Views"
x:Class="MyProject.Views.SettingsMasterPage"
IconImageSource="menu.png"
Padding="0,40,0,0"
Title="Menu">
<StackLayout>
<ListView x:Name="listView" x:FieldModifier="public">
<ListView.ItemsSource>
<x:Array Type="{x:Type local:MasterPageItem}">
<local:MasterPageItem Title="Settings Link 1" />
<local:MasterPageItem Title="Settings Link 2" />
<local:MasterPageItem Title="Settings Link 3" />
</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>
</StackLayout>
</ContentPage>
MyTabbedPage.xaml
<TabbedPage 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:views="clr-namespace:MyProject.Views;assembly=MyProject"
x:Class="Xamarin.Sigma01.Views.LoggerDetectionTabbedPage"
android:TabbedPage.ToolbarPlacement="Bottom"
BarBackgroundColor="White"
SelectedTabColor="Black"
BarTextColor="Black">
<TabbedPage.Children>
<views:MainPage IconImageSource="tab_icon_mainpage.png" />
<!-- second link should be the sandwhich button that brings up the settings page -->
</TabbedPage.Children>
</TabbedPage>
MainPage.xaml (the main page, navigated to by the left TabBar link icon, to the left of the sandwhich icon with title "More")
<ContentPage.Content>
<StackLayout>
<Label Text="Welcome to the Main page!"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage.Content>
An easy way I can achieve the effect is to use Shell. It's released for months and just check your VS version for the correct template.
Create a new Xamarin.Forms project using VS2019.
You can use Shell out of the box if you can see the following screen.
Find "ItemsPage.xaml" in the Views folder.
Add one line in the ContentPage at the top
<ContentPage
...
Shell.TabBarIsVisible="False">
Add a StackLayout to contain the existing CollectionView and add your bottom buttons.
<RefreshView ...>
<!-- new StackLayout -->
<StackLayout>
<CollectionView ..... />
<!-- new Buttons -->
<StackLayout
HeightRequest="52"
Orientation="Horizontal"
BackgroundColor="#2196F3"
Visual="Material">
<Button
WidthRequest="200"
BackgroundColor="Transparent"
Text="Refresh"
Command="{Binding LoadItemsCommand}" />
<Button
BackgroundColor="Transparent"
Text="More"
Clicked="Button_Clicked" />
</StackLayout>
</StackLayout>
Go to "ItemsPage.xaml.cs" to complete the button event, add a method:
private void Button_Clicked(object sender, EventArgs e)
{
Shell.Current.FlyoutIsPresented = true;
}
Set startup project and deploy, check the effect and play around.
Additionally, in the latest Xamarin.Forms, UWP Shell is an experimental feature, and so does in XF 5.0. But the flyout things will probably work fine (not too sure about this).
An alternative, following the idea from #Shaw, but without Shell is to use the good old MasterDetail Page (which supports UWP) and add two buttons at the bottom to provide the "More" and "Refresh" functionality.
If this sounds like a good option for you, keep reading:
Add a Master-Detail Page to your Solution
On Visual Studio 2019 adding a Master-Detail to your solution is pretty straight forward. You only need to right click the Xamarin.Forms Project in the Solution Explorer and go to Add -> New Item (or simply use the shortcut Ctrl+Shift+A):
in the window that appears, select Master-Detail Page, give it a cool name (MasterDetailPage1 in this example!) and click Add:
By doing this you successfully have added a Master Detail to your solution. Now just go to App and set MainPage to it as follows:
MainPage = new MasterDetailPage1();
Add the bottom buttons
Now we want two buttons at the bottom of our Detail page. This is simply done by adding a stack of two buttons that locate at the end. Our newly added MasterDetailPage1Detail.xaml will then look like:
<?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="MasterTabRefresh.MasterDetailPage1Detail"
Title="Detail">
<StackLayout>
<Label Text="This is a detail page. To get the 'triple' line icon on each platform add a icon to each platform and update the 'Master' page with an Icon that references it."
Padding="10"/>
<StackLayout Orientation="Horizontal"
VerticalOptions="EndAndExpand"
Spacing="0">
<Button BackgroundColor="CornflowerBlue"
Text="Refresh"
TextColor="White"
CornerRadius="0"
HorizontalOptions="FillAndExpand"/>
<Button BackgroundColor="CornflowerBlue"
Text="More"
TextColor="White"
CornerRadius="0"
HorizontalOptions="FillAndExpand"
Clicked="MoreClicked"/>
</StackLayout>
</StackLayout>
</ContentPage>
which should look like:
And in the code behind (MasterDetailPage1Detail.xaml.cs ) we add the "More" functionality:
private void MoreClicked(object sender, EventArgs e)
{
((MasterDetailPage)Application.Current.MainPage).IsPresented = !((MasterDetailPage)Application.Current.MainPage).IsPresented;
}
Add a nice X (close) button to your menu/master
This could be achieved by adding a label with an "X" at the top right of the menu.
Simply modify your MasterDetailPage1Master.xaml to look like (note Label at Column 2 Row 0!)
<?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="MasterTabRefresh.MasterDetailPage1Master"
Title="Master">
<StackLayout>
<ListView x:Name="MenuItemsListView"
SeparatorVisibility="None"
HasUnevenRows="true"
ItemsSource="{Binding MenuItems}">
<ListView.Header>
<Grid BackgroundColor="#03A9F4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="80"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="10"/>
</Grid.RowDefinitions>
<Label Grid.Column="2"
Grid.Row="0"
Text="X"
FontAttributes="Bold"
HorizontalTextAlignment="Center"
VerticalTextAlignment="Center">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="X_Tapped"/>
</Label.GestureRecognizers>
</Label>
<Label
Grid.Column="1"
Grid.Row="2"
Text="My wonderful App"
Style="{DynamicResource SubtitleStyle}"/>
</Grid>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="15,10" HorizontalOptions="FillAndExpand">
<Label VerticalOptions="FillAndExpand"
VerticalTextAlignment="Center"
Text="{Binding Title}"
FontSize="24"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
Which should look like this:
And then add the "Close" functionality to that "X" Label in the code behind (MasterDetailPage1Master.xaml):
private void X_Tapped(object sender, EventArgs e)
{
((MasterDetailPage)Application.Current.MainPage).IsPresented = false;
}
And that is it! This should get you going. Happy coding!
how to add a click event for entry which is in disable state?
I tried with gesture recognizer like below:
<Entry
TextColor="Black"
x:Name="phone">
<Entry.GestureRecognizers>
<TapGestureRecognizer
Tapped="StartCall"
NumberOfTapsRequired="1">
</TapGestureRecognizer>
</Entry.GestureRecognizers>
</Entry>
void StartCall(object sender,EventArgs args)
{
DisplayAlert("Alert","Hi","ok");
}
No alert showing on ui when tapping on entry.
Thanks in advance
Put your entry inside layout and give GestureRecognizers to layout.
e.g
<StackLayout>
<Entry
Placeholder="Enter Phone Number"
IsEnabled="False"
TextColor="Black"
x:Name="phone"/>
<StackLayout.GestureRecognizers>
<TapGestureRecognizer
Tapped="StartCall"
NumberOfTapsRequired="1">
</TapGestureRecognizer>
</StackLayout.GestureRecognizers>
</StackLayout>
Just Put your Button in a Layout(StackLayout for example) that handles your Event
<StackLayout>
<StackLayout.GestureRecognizers>
<TapGestureRecognizer
Tapped="StartCall">
</TapGestureRecognizer>
</StackLayout.GestureRecognizers>
<!-- InputTransparent="True" to avoid conflicts -->
<Entry InputTransparent="True"
TextColor="Black"
x:Name="phone"/>
<StackLayout>
As #Diego Rafael Souza said
Entry having Focused event it will fire while user tap on Entry
XAML:
<Entry Placeholder="Phone number" TextColor="Black" x:Name="phone" Focused="StartCall"/>
.cs:
void StartCall(object sender, EventArgs args){
DisplayAlert("Alert", "Hi", "ok");
}
Put it in a grid layout
<Grid>
<Entry IsEnabled="False" Text="Hello"/>
<StackLayout>
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Command="{Binding EntryTapCommand}" />
</StackLayout.GestureRecognizers>
</StackLayout>
</Grid>