I want to change focus from one entry to other entry.
At first, I changed with Focus() method for all entry. But I think it's not good code, because the more entry, the more difficult to edit.
So I found reference from here https://adenearnshaw.com/focus-next-element-on-enter/
First, create behavior
public class SetFocusOnEntryCompletedBehavior : Behavior
{
public static readonly BindableProperty TargetElementProperty
= BindableProperty.Create(nameof(TargetElement), typeof(VisualElement), typeof(SetFocusOnEntryCompletedBehavior));
public VisualElement TargetElement
{
get => (VisualElement)GetValue(TargetElementProperty);
set => SetValue(TargetElementProperty, value);
}
protected override void OnAttachedTo(BindableObject bindable)
{
base.OnAttachedTo(bindable);
if (bindable is Entry entry)
entry.Completed += Entry_Completed;
}
protected override void OnDetachingFrom(BindableObject bindable)
{
if (bindable is Entry entry)
entry.Completed -= Entry_Completed;
base.OnDetachingFrom(bindable);
}
private void Entry_Completed(object sender, EventArgs e)
{
TargetElement?.Focus();
}
}
Next, implement in xaml
<ContentPage x:Class="NextFormFieldSample.Forms.MainPage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:behaviors="clr-namespace:NextFormFieldSample.Forms.Behaviors">
<StackLayout Margin="20">
<Entry Placeholder="Field 1">
<Entry.Behaviors>
<behaviors:SetFocusOnEntryCompletedBehavior TargetElement="{x:Reference Entry2}" />
</Entry.Behaviors>
</Entry>
<Entry x:Name="Entry2" Placeholder="Field 2"/>
</StackLayout>
</ContentPage>
But!!!! I have to add one more thing for using this.
I have to receive result after entry completed event; If the result is true, focus changed. If not, focus stayed again.
I tried to make behaviors. But it's very difficult for me.
Are there anybody help me?
That is, with some result from database, if the result is true, focus
is changed. But if that is false, focus stay on same entry. Not only
just change the focus of entry, but watch the result from database.
Then you can add some logical judgment to the event Entry_Completed.
Please refer to the following code:
<ContentPage.Content>
<StackLayout Margin="20">
<Entry x:Name="Entry1"
Placeholder="Field 1"
Completed="Entry_Completed"
TabIndex="1">
</Entry>
<Entry x:Name="Entry2"
Placeholder="Field 2"
Completed="Entry_Completed"
TabIndex="2">
</Entry>
<Entry x:Name="Entry3"
Placeholder="Field 3"
Completed="Entry_Completed"
TabIndex="3">
</Entry>
<Entry x:Name="Entry4"
Placeholder="Field 4"
Completed="Entry_Completed"
TabIndex="4" />
</StackLayout>
</ContentPage.Content>
Event Entry_Completed in YourPage.xaml.cs
private void Entry_Completed(object sender, EventArgs e)
{
var entry = sender as Entry; // .. and check for null
// get result from database here
if (entry.Text.Length == 2) // here I used string's length(2) as the logical condition
{
var list = (entry.Parent as StackLayout).Children; //assumes a StackLayout
var index = list.IndexOf(entry); //
var nextIndex = (index + 1) >= list.Count ? 0 : index + 1; //first or next element?
var next = list.ElementAt(nextIndex);
next?.Focus();
}
}
Related
I have created custom tab control using ScrollView control and Bindable StackLayout control.
I have first created this solution in Xamarin.Forms (VS for Mac 2019) and it works fine in both platforms, but the same solution when developed in .Net MAUI (VS for Mac 2022 Prev) it's not working properly in Android.
Update 30 Jun 2022
There is an issue with BindableLayout (StackLayout) properties in MAUI currently so when we are changing values it does not get reflected, and because of this, I think I'm facing this issue. Here is the reference
Here is what I have done so far:
MainPage.xaml
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:vm="clr-namespace:poc_maui.ViewModels"
x:Class="poc_maui.Views.HomePage"
xmlns:tabs="clr-namespace:poc_maui.Views.SubViews"
Title="HomePage">
<ContentPage.BindingContext>
<vm:MainPageViewModel />
</ContentPage.BindingContext>
<Grid RowDefinitions="50, *" RowSpacing="0">
<ScrollView Grid.Row="0" Orientation="Horizontal" VerticalOptions="Start" HorizontalScrollBarVisibility="Never"
Scrolled="ScrollView_Scrolled">
<StackLayout x:Name="TabsView"
Orientation="Horizontal"
BindableLayout.ItemsSource="{Binding Tabs}" Spacing="0">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Grid RowDefinitions="*, 4" RowSpacing="0">
<Label Grid.Row="0"
Text="{Binding TabTitle}"
TextColor="White"
BackgroundColor="navy"
Padding="20,0"
VerticalTextAlignment="Center"
HorizontalTextAlignment="Center"
FontSize="12"
HeightRequest="40"/>
<BoxView Grid.Row="1"
Color="Yellow"
IsVisible="{Binding IsSelected}"/>
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Path=BindingContext.TabChangedCommand,
Source={x:Reference TabsView}}"
CommandParameter="{Binding .}"/>
</Grid.GestureRecognizers>
</Grid>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</ScrollView>
<tabs:ParentRecordTabView Grid.Row="1" IsVisible="{Binding IsParentRecordTabVisible}"
VerticalOptions="FillAndExpand"/>
<tabs:AdditionalInfoTabView Grid.Row="1" IsVisible="{Binding IsAdditionalInfoTabVisible}"
VerticalOptions="FillAndExpand" />
</Grid>
</ContentPage>
MainPageViewModel
using System;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Windows.Input;
using poc_maui.Models;
namespace poc_maui.ViewModels
{
public class MainPageViewModel : BaseViewModel
{
#region Constructor
public MainPageViewModel()
{
GetTabs();
}
#endregion
#region Private Properties
private bool _isParentRecordTabVisible = true;
private bool _isAdditionalInfoTabVisible;
private ObservableCollection<TabViewModel> _tabs { get; set; }
#endregion
#region Public Properties
public bool IsParentRecordTabVisible
{
get => _isParentRecordTabVisible;
set { _isParentRecordTabVisible = value; OnPropertyChanged(nameof(IsParentRecordTabVisible)); }
}
public bool IsAdditionalInfoTabVisible
{
get => _isAdditionalInfoTabVisible;
set { _isAdditionalInfoTabVisible = value; OnPropertyChanged(nameof(IsAdditionalInfoTabVisible)); }
}
public ObservableCollection<TabViewModel> Tabs
{
get => _tabs;
set { _tabs = value; OnPropertyChanged(nameof(Tabs)); }
}
#endregion
#region Commands
public ICommand TabChangedCommand { get { return new Command<TabViewModel>(ChangeTabClick); } }
#endregion
#region Private Methods
private void GetTabs()
{
Tabs = new ObservableCollection<TabViewModel>();
Tabs.Add(new TabViewModel { TabId = 1, IsSelected = true, TabTitle = "Parent record" });
Tabs.Add(new TabViewModel { TabId = 2, TabTitle = "Additional Info" });
Tabs.Add(new TabViewModel { TabId = 3, TabTitle = "Contacts" });
Tabs.Add(new TabViewModel { TabId = 4, TabTitle = "Previous inspections" });
Tabs.Add(new TabViewModel { TabId = 5, TabTitle = "Attachments" });
SelectedTab = Tabs.FirstOrDefault();
}
private void ChangeTabClick(TabViewModel tab)
{
try
{
var tabs = new ObservableCollection<TabViewModel>(Tabs);
foreach (var item in tabs)
{
if (item.TabId == tab.TabId)
{
item.IsSelected = true;
}
else
{
item.IsSelected = false;
}
}
Tabs.Clear();
Tabs = new ObservableCollection<TabViewModel>(tabs);
switch (tab.TabId)
{
case 1:
IsParentRecordTabVisible = true;
IsAdditionalInfoTabVisible = false;
break;
case 2:
IsParentRecordTabVisible = false;
IsAdditionalInfoTabVisible = true;
break;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
#endregion
}
}
#ParentTabView.xaml
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="poc_maui.Views.SubViews.ParentTabView">
<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="CenterAndExpand" >
<Label
Text="Welcome to Parent tab!"
VerticalOptions="Center"
HorizontalOptions="Center" />
</StackLayout>
</ContentView>
#AdditionalInfoTabView.xaml
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="poc_maui.Views.SubViews.AdditionalInfoTabView">
<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="CenterAndExpand" >
<Label
Text="Welcome to Additiona info tab!"
VerticalOptions="Center"
HorizontalOptions="Center" />
</StackLayout>
</ContentView>
So what happens here in Android is when I'm clicking AdditionalInfo Tab then it will show a blank white screen and if you press the hardware back button and open the app again it will show AdditionalTab as selected and its views content as well.
If I remove switch() code part from the ViewModel then it will work fine but tabs will not change. Does anyone have idea about this kind of behavior of scroll view in MAUI?
The full source code is here: maui_sample
Does this work-around fix it?
MainPage.xaml:
<ScrollView x:Name "theScrollView" ... >
MainPage.xaml.cs:
public MainPage()
{
InitializeComponent();
MessagingCenter.Subscribe<MainPageViewModel>(this, "update", (sender) =>
{
// Tell theScrollView to re-layout its contents.
(theScrollView as IView).InvalidateArrange();
});
}
MainPageViewModel:
private void ChangeTabClick(TabViewModel tab)
{
... make changes ...
MessagingCenter.Send<MainPageViewModel>(this, "update");
}
MAYBE:
I'm not sure if MessagingCenter Subscribe is on Dispatcher (Main) thread. To be reliable, do:
MessagingCenter.Subscribe<MainPageViewModel>(this, "update", (sender) =>
{
Dispatcher.Dispatch( () =>
{
(theScrollView as IView).InvalidateArrange();
});
}
UPDATE
There are other Maui bugs, that have a common "theme": Maui on Android does "something" related to layout only once - at the time the page is first drawn. UNFORTUNATELY, anything that is "not visible" at that time, is skipped. And won't work when later made visible.
Until such bugs are fixed, you'll have to do some work-around.
WORK-AROUND #1:
Start with ALL tabs IsVisible="True".
As soon as the page has been drawn the first time, in code-behind, create the desired Bindings on those IsVisible properties. Page drawn first time can be intercepted in a custom handler. But this is a temp work-around, so its easier to just run a method after a 250 ms delay. Use a boolean "flag" to make the method only run the first time.
Might have to do InvalidateArrange as shown above, to force the Bindings to function the first time.
OR WORK-AROUND #2:
Each time tab changes, use shell route to go to MainPage again. Keep same view model, so knows which tab to show first (and remembers any other state you care about).
Both of these are ugly.
I recommend creating an issue at .Net Maui github, and providing link to your github sample.
This is still not works for me properly but after looking at below two links I found that it it not what we are looking for. The Isvisible : false first and then on switch or check box change you are trying to make it visible then it will not visible but the actual control visible. So on look after I have see this link but again the answer is not what I was looking for.
Step to resolve.
On View use the Parent as ScrollView or control belongs to IView,IElement.
<ScrollView x:Name "myScrollView">
.....
...
Add Action on ViewModel
public delegate void Action(T obj);
Invoke the Action
Note: Make sure you call this on require not all the time.
e.g. On Visibility set in ViewModel call after visibility update.
MeasureAction?.Invoke("reSetVisibility");
Now on View's Code File, use Viewmodel and accept the invoke
Here Call the below line will works perfectly.
(myScrollView as IView).InvalidateMeasure();
That's IT... Enjoy IsVisible now and make your layout as require.
On Page#1, i have a collectionview with text/string items list. If you tap a a item, it will get the current tapped text/string and send to Page#2. sound simple
issue I am having: if you tap on item#1, then it will send item#1 to page2, this part working fine. But on page#2, if you hit back button, and tap on item#1 again.. than nothing happens, it doesnt go to page#2
Fix: i think i need to somehow clear tap selection, and than send the item to page#2. but im not sure how to do this
On Page#1, i have a simple collectionview. Collection view contains text/string list
<CollectionView ItemsSource="{Binding MyListItem}"
SelectionMode="Single"
SelectionChanged="CollectionView_SelectionChanged">
<CollectionView.ItemTemplate>
<DataTemplate>
<ContentView>
<!-- Body -->
<Grid Padding="0">
<Frame CornerRadius="3" BorderColor="#f2f4f5" HasShadow="True">
<StackLayout Orientation="Horizontal">
<Image Source="icon_about"
WidthRequest="25" />
<StackLayout VerticalOptions="Center">
<Label VerticalOptions="Center"
FontSize="16"
Text="{Binding .}" />
</StackLayout>
</StackLayout>
</Frame>
back end code to handle selection is:
private async void CollectionView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var previous = e.PreviousSelection.FirstOrDefault();
var current = e.CurrentSelection.FirstOrDefault();
var route = $"{ nameof(Page2) }?URLCardType={current}";
await Shell.Current.GoToAsync(route);
//clear selection
((CollectionView)sender).SelectedItem = null;
}
Update ((CollectionView)sender).SelectedItem = null; fixed the issue of clearing selected item but CollectionView_SelectionChanged method is get run twice on single tap. why? this is all the code i have
#jason thanks, this worked for me. i just had to check if selection item is null than do nothing
private async void CollectionView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var MyCollectionView = sender as CollectionView;
if (MyCollectionView.SelectedItem == null)
return;
var previous = e.PreviousSelection.FirstOrDefault();
var current = e.CurrentSelection.FirstOrDefault();
var route = $"{ nameof(Page2) }?URLCardType={current}";
await Shell.Current.GoToAsync(route);
//clear selection
MyCollectionView.SelectedItem = null;
}
Here is a simple solution that worked for me.
Setting to null did not do the trick, it was causing all kinds of
weird stuff.
private void CollectionView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var itemselected = e.CurrentSelection[0] as ProductsItem;
if (itemselected != null)
Shell.Current.GoToAsync(nameof(SelectedProductPage));
//Setting the selected item to an emptyviewproperty after navigation
CollectionList.SelectedItem = SelectableItemsView.EmptyViewProperty;
}
I have a ContentPage that is bound to a viewmodel. Still, at one point, I need to access a Picker inside a StackLayout which in turn is in a Syncfusion ListViewItem. The XAML is pretty straightforward:
<?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:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:sf="clr-namespace:Syncfusion.ListView.XForms;assembly=Syncfusion.SfListView.XForms"
mc:Ignorable="d"
x:Class="PerformanceTM.Views.NewCircuitView">
<ContentPage.Content>
<StackLayout>
<Label Text="Welcome to Xamarin.Forms!"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand" />
<sf:SfListView x:Name="ExerciseList" ItemsSource="{Binding Exercises}" DragStartMode="OnHold">
<sf:SfListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<Picker Title="Kategorie" x:Name="CategoryPicker" ItemsSource="{Binding Source={x:Reference ExerciseList}, Path=BindingContext.ExerciseCategories}" ItemDisplayBinding="{Binding Name}" SelectedItem="{Binding Category}" SelectedIndexChanged="CategoryChanged"/>
<Picker Title="Übung" x:Name="ExerciseNamePicker" ItemDisplayBinding="{Binding Name}" SelectedIndexChanged="ExerciseSelected"/>
<Button Text="..." Clicked="ConfigureSetsClicked"/>
<Button Text="(-)" />
</StackLayout>
</ViewCell>
</DataTemplate>
</sf:SfListView.ItemTemplate>
</sf:SfListView>
<StackLayout Orientation="Horizontal">
<Button Text="(+) Übung" Command="{Binding AddExerciseCommand}"/>
<Button Text="Ok" Command="{Binding ApplyChangesCommand}"/>
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>
As you can see, both Pickers in the ViewCell have x:Name assigned to them. When I select a value in the ExerciseCategoryPicker, I load and assign new values to to ExerciseNamePicker in Code behind, like so:
private async void CategoryChanged(object sender, EventArgs e)
{
var picker = sender as Picker;
var stackLayout = picker.Parent as StackLayout;
ListViewItem listViewItem = stackLayout.Parent as ListViewItem;
var ex = picker.BindingContext as Exercise;
if (ex is null)
return;
ex.Category = picker.SelectedItem as ExerciseCategory;
var apiService = new ApiServices();
var exsForCategory = await apiService.GetExercisesForCategory(ex.Category.Name);
Picker exnp = stackLayout.FindByName<Picker>("ExerciseNamePicker");
if (exnp is null)
exnp = stackLayout.Children.OfType<Picker>().Where(x => x.Title == "Übung").FirstOrDefault();
exnp.ItemsSource = exsForCategory;
if (exsForCategory.Count > 0)
exnp.SelectedItem = exsForCategory.FirstOrDefault();
var bc = this.BindingContext as NewCircuitViewModel;
bc.ExercisePairing.Descriptor = bc.ExercisePairing.UpdateDescriptor();
}
private void ExerciseSelected(object sender, EventArgs e)
{
try
{
var picker = (sender as Picker);
var stackLayout = picker.Parent as StackLayout;
var vc = picker.Parent.Parent as Syncfusion.ListView.XForms.ListViewItem;
var ex = vc.BindingContext as Exercise;
var se = picker.ItemsSource[picker.SelectedIndex] as Exercise;
var exnp = stackLayout.FindByName("CategoryPicker") as Picker;
if (exnp is null)
exnp = stackLayout.Children.OfType<Picker>().Where(x => x.Title == "Kategorie").FirstOrDefault();
var ec = exnp.SelectedItem as ExerciseCategory;
ex.Category = ec;
ex.Name = se.Name;
ex.Id = se.Id;
ex.Description = se.Description;
ex.VideoUrl = se.VideoUrl;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Now what happens is that FindByName() returns null in each situation. Oddly enough, when I debug and inspect the Children of StackLayout just before calling FindByName, it does contain children with the appropriate IDs (i.e., the x:Name). When I access them via get, I get the GUID (this somehow confuses me, as I thought there should only be a GUID in the first place, but well).
I have found a workaround by just selecting the element by Title, but this is a rather strange behaviour, especially considering that this has worked in the past. Only change I made since then was the integration of the SyncFusion ListView. Could that be an issue? Has anyone experienced this and/or can provide more insight?
PS: I have gone through all the "usual" fixes such as deleting the .v, bin and obj folders...
You can get the children element of SfListView.ItemTemplate using behavior for the parent element of the ItemTemplate. Please refer the following code snippet for getting the named elements inside DataTemplate,
Xaml: Define Behavior for StackLayout
<sf:SfListView x:Name="ExerciseList" ItemsSource="{Binding Exercises}" DragStartMode="OnHold">
<sf:SfListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<StackLayout.Behaviors>
<local:Behavior/>
</StackLayout.Behaviors>
<Picker Title="Kategorie" x:Name="CategoryPicker" ItemsSource="{Binding Source={x:Reference ExerciseList}, Path=BindingContext.ExerciseCategories}" ItemDisplayBinding="{Binding Name}" SelectedItem="{Binding Category}"/>
<Picker Title="Übung" x:Name="ExerciseNamePicker" ItemDisplayBinding="{Binding Name}"/>
<Button Text="..." Clicked="ConfigureSetsClicked"/>
<Button Text="(-)" />
</StackLayout>
</ViewCell>
</DataTemplate>
</sf:SfListView.ItemTemplate>
Behavior: Get element using FindByElement. Trigger SelectedIndexChanged event for Picker.
public class Behavior : Behavior<StackLayout>
{
Picker CategoryPicker;
Picker ExerciseNamePicker;
protected override void OnAttachedTo(StackLayout bindable)
{
CategoryPicker = bindable.FindByName<Picker>("CategoryPicker");
ExerciseNamePicker = bindable.FindByName<Picker>("ExerciseNamePicker");
CategoryPicker.SelectedIndexChanged += CategoryPicker_SelectedIndexChanged;
ExerciseNamePicker.SelectedIndexChanged += ExerciseNamePicker_SelectedIndexChanged;
base.OnAttachedTo(bindable);
}
private void ExerciseNamePicker_SelectedIndexChanged(object sender, EventArgs e)
{
//Your logic here.
}
private void CategoryPicker_SelectedIndexChanged(object sender, EventArgs e)
{
//Your logic here.
}
}
You can also refer our online document regarding the same from the following link,
Document
I don't get something, I would like, from a button, open my DatePicker. So I coded that:
private void OnDateClicked(object sender, EventArgs ea)
{
Debug.WriteLine("PLOPPP");
//DatePickerControl.IsVisible = true;
//DatePickerControl.Focus();
Device.BeginInvokeOnMainThread(() => {
DatePickerControl.Focus();
});
}
Once the button got clicked/touched by the user, nothing happens.. Why? I'm just searching to open the Date Selector but I can't figure out why it doesn't work ><
The XAML part is looking like that:
<AbsoluteLayout x:Name="LayoutTools"
AbsoluteLayout.LayoutBounds="0.5, 0.05, 0.9, 0.075"
AbsoluteLayout.LayoutFlags="All">
<!-- DATE -->
<!--<control:SquareLayout x:Name="DateButton" BackgroundColor="{x:StaticResource NL_BlueNight}" ScalingBase="Height"
AbsoluteLayout.LayoutBounds="0, 0.5, 0.1, 1"
AbsoluteLayout.LayoutFlags="All"/>-->
<AbsoluteLayout x:Name="DateButton" BackgroundColor="{x:StaticResource NL_BlueNight}" Opacity="0.8"
AbsoluteLayout.LayoutBounds="0, 0.5, 0.1, 1"
AbsoluteLayout.LayoutFlags="All">
<control:CustomLabel Text="{Binding DaySelected}" FontFamily="{extension:FontFamily Roboto_Light}" FontSize="20" TextColor="Gray"
HorizontalTextAlignment="Center" VerticalTextAlignment="Center"
AbsoluteLayout.LayoutBounds="0.5, 0.5, 1, 1"
AbsoluteLayout.LayoutFlags="All"/>
<Button Clicked="OnDateClicked" BackgroundColor="Transparent" BorderColor="Transparent"
AbsoluteLayout.LayoutBounds="0.5, 0.5, 1, 1"
AbsoluteLayout.LayoutFlags="All"/>
</AbsoluteLayout>
</AbsoluteLayout>
<!-- <control:CustomDatePicker.../> -->
So here, the CustomLabel is bind to an object which give the number of the current day. Over it, a Button which call the private void OnDateClicked(object sender, EventArgs ea) method.
Then, in this method, I'm trying to open the DatePicker I have put in the XAML part:
<!-- code above -->
<control:CustomDatePicker x:Name="DatePickerControl" Format="dd-MM-yyyy" Date="{Binding CurrentDate}" IsVisible="False"
MinimumDate="{Binding CurrentDate}"
FontFamily="{extension:FontFamily Roboto_Light}" FontSize="20" TextColor="White"
XAlign="Center" HasBorder="false" BackgroundColor="Transparent"
AbsoluteLayout.LayoutBounds="0.5, 0.5, 1, 1"
AbsoluteLayout.LayoutFlags="All"/>
The idea is just to open the selector, then I save the all date but only display the day of this selected date, in the Label.
Thank in advance !
It's known issue. Maybe it would be fixed in the future. I could suggest my workaround with using renderer for UWP:
[assembly: ExportRenderer(typeof(DatePickerRenderer), typeof(SomeDatePickerRenderer))]
namespace SuperForms.UWP.Renderers
{
public class SomeDatePickerRenderer : DatePickerRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.DatePicker> e)
{
base.OnElementChanged(e);
if (Control != null)
{
// TODO: Focus() doesn't open date picker popup on UWP, it's known issue
// on Xamarin.Forms and should be fixed in 2.5. Had to open it manually.
var flyout = new DatePickerFlyout() { Placement = FlyoutPlacementMode.Top };
flyout.DatePicked += (s, args) =>
{
Control.Date = args.NewDate;
};
FlyoutBase.SetAttachedFlyout(Control, flyout);
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == VisualElement.IsFocusedProperty.PropertyName)
{
if (Element.IsFocused)
{
FlyoutBase.ShowAttachedFlyout(Control);
}
}
}
}
}
Now it's being shown each time when IsFocus change to true, so you need to set up it due to your requirements.
I would like to figure out, how to keep my label text appear after label animation completion. My idea is that I have Label on top and Entry field behind it. Until there isn't any text in entry, my label is empty, but when I starting to type my label appear with animation over and over after each newly typed character. I already did that, but I wan't that it will appear with animation one time, and then keep showing my regular label without repeating animation. Because now my label shows with animation and do no keep, it disappears immediately.
Here is my xaml code:
<?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.MyPage">
<ContentPage.Content>
<StackLayout Padding="7,7,7,7" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" Spacing="0">
<StackLayout BackgroundColor="White">
<Label x:Name="NameText" />
<Entry x:Name="Name" />
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>
and here is my C# code with EventHandler: TextChange
public MyPage()
{
InitializeComponent();
Name.TextChanged += Name_TextChanged;
}
private async void Name_TextChanged(object sender, TextChangedEventArgs e)
{
NameText.Animate("nameAnimation", new Animation(v => NameText.Scale = v, 1, 2, Easing.SpringIn));
NameText.Text = "MyLabel";
}
How to my label appear and complete animation action only one time?
Thank you for answers or suggestions.
Detach your handler after the animation:
async void Name_TextChanged(object sender, TextChangedEventArgs e)
{
NameText.Animate("nameAnimation", new Animation(v => NameText.Scale = v, 1, 2, Easing.SpringIn));
NameText.Text = "MyLabel";
Name.TextChanged -= Name_TextChanged;
}