Focus on entry in listview on android - xamarin

So i need to allow the user to get access to each entry field within the listview to enter a value, my code runs fine on iOS but once to try it on android i cant get access to the entry box, once the entry field is tapped it will show the cursor but it will not focus on the entry field and you cannot type anything as the keyboard doesnt appear. Does anyone have any idea how to fix this issue ?
<ListView x:Name="btnlist" Margin="0,0,0,20" Grid.Row="8" Grid.Column="1" Grid.ColumnSpan="2" AutomationId="ListMed"
CachingStrategy="RecycleElement" RowHeight="65" IsPullToRefreshEnabled="False" IsVisible="false" SeparatorColor="transparent"
>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell Appearing="Handle_Appearing1">
<local:XFDoneEntry x:Name="txtFrequency" Text="{Binding Count}" Day="{Binding Placeholder}" wdaynum="{Binding Wdaynum}" Placeholder="{Binding Placeholder}" Unfocused="Leave_box" VerticalOptions="Center" Keyboard="Numeric" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3"/>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
//This is the code i use to find the entry boxes within the listview.
void Handle_Appearing1(object sender, System.EventArgs e)
{
var ViewcellAll1 = (ViewCell)sender;
ddoneentry = ViewcellAll1.View.FindByName<XFDoneEntry>("txtFrequency");
}
//this is the app with the listviews, depending on which days the user chooses the appropriate entry fields are populated within the second listview with entries.

Related

Xamarin form carouselview scrolls with multiple items for single scroll

Iam using Carousel view control available in Xamarin form(Version 5).
In my case i used Listviews inside carousel view. It works fine if scroll by swiping to left or right, but if i programmatically set the ScrollTo or Position property for the carousel view using button click then it is scrolling multiple times though i'm setting single incremental value.
I added SnapPointsType="MandatorySingle" as mentioned here
One more issue is if my current carousel position is zero and moving to last position or more then one is not working.
<AbsoluteLayout Margin="2" BackgroundColor="Transparent">
<CarouselView
x:Name="MyCarousalView"
AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="All"
Scrolled="CarouselViewScrolled">
<CarouselView.ItemsLayout>
<LinearItemsLayout Orientation="Horizontal" ItemSpacing="0" SnapPointsType="MandatorySingle" />
</CarouselView.ItemsLayout>
<CarouselView.ItemTemplate>
<DataTemplate>
<ListView
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
ItemsSource="{Binding .}"
x:FieldModifier="public">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell Tapped="ViewCellTapped">
<StackLayout Padding="0">
<StackLayout Padding="20,1" VerticalOptions="StartAndExpand" Spacing="0" >
<Label
FontSize="16"
Text="{Binding Description}"
FontAttributes="Bold"/>
<Label
FontSize="14"
Text="{Binding CreatedDate}" />
</StackLayout>
<Label HorizontalOptions="FillAndExpand" Padding="0" HeightRequest="1" BackgroundColor="#D4D4D4"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</AbsoluteLayout>
Next button click event
private void NextClicked(object sender, EventArgs e)
{
MyCarousalView.ScrollTo((MyCarousalView.Position + 1) < _weekDaysList.Count ? MyCarousalView.Position + 1 : 0);
}
Carousel view binding:
List<List<Note>> _myList;
_myList=getData(); //based on service response
MyCarousalView.ItemsSource = null;
MyCarousalView.ItemsSource = _myList;
Screen recording with issue image
Screen video
Please letme know if any solution/workaround. Thanks

Sort ListView by pressing a button

I have a ListView and wish to sort it up and down. Here is the xaml
<ListView x:Name="ListRegister" ItemsSource="{Binding Registrations}" HasUnevenRows="True" SelectionMode="Single">
<ListView.Behaviors>
<b:EventToCommandBehavior EventName="ItemTapped" Command="{Binding CommandGoDetail}" EventArgsParameterPath="Item" />
</ListView.Behaviors>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<Frame >
<StackLayout>
<Label Text="{Binding Date}" Style="{StaticResource registerItemDateText}"/>
</StackLayout>
</Frame>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
As well as the "button" (alternates between my SortUp() and sortDown() functions). The button changes a text to "up" and "down" so I know it works on screen.
<TapGestureRecognizer Command="{Binding CommandSort}"/>
These function seem to work
Registrations.Sort((x, y) => DateTime.Compare(y.Date, x.Date));
Registrations.Sort((x, y) => DateTime.Compare(x.Date, y.Date));
The list is correctly sorted Up or Down when one of those functions is called but when the button is Pressed, the list does not updates itself to the other sorting.
Where did I mess up ?
EDIT :
CommandSort code
private void HandleSort(Registration obj)
{
if(SortRecent)
{
SortRecent = false;
SortText = "Plus ancien";
SortImageSource = "lightDownArrow";
SortDown();
}
else
{
SortRecent = true;
SortText = "Plus récent";
SortImageSource = "lightUpArrow";
SortUp();
}
}
Registrations is of type :
List<Registration> Registrations
A Registration having a string name, and a DateTime date
You need to check what type of data is Registrations. It must be an Observable Collection in order to inform the UI about the changes made to the model. If not, You will need to manually update the list view to reflect the changes made to the model, in this case, the new sorting direction. You could use :
ListView.BeginRefresh(); & ListView.EndRefresh(); to force the update of the list view. But it is highly recommended to change your list to an observable collection.

How to set Focus to entry in xamarin forms

I want to add focus() to my entry field, When I add the entry.Focus() it's work fine in the entry's in top of the page.But when comes to the bottom it doesn't work smoothly.And also I tried with SoftInput method but it hides the entry in the bottom and also the design is changing when a page has only one or two entry.
Please help me
The #AbbyWang answer is correct, also you can use the ReturnCommand property.
<StackLayout
Orientation="Vertical">
<Entry
x:Name="firstLabel"
ReturnType="Next"
FontSize="Small"
TextColor="Black" />
<Entry
x:Name="secondLabel"
ReturnType="Done"
FontSize="Small"
TextColor="Black" />
</StackLayout>
And the code behind
public YourPage()
{
InitializeComponent();
this.firstLabel.ReturnCommand = new Command(() => this.secondLabel.Focus());
// or you can use this to call a command on your viewmodel
this.secondLabel.ReturnCommand = new Command(() => YourViewModel.SomeCommand.Execute(null));
}
If you just have two Entries on your page, you can simply add a Completed event to your top entry, and call the entry.Focus() for bottom entry in this event. So the code is like this:
MainPage.xaml:
<StackLayout>
<StackLayout Orientation="Horizontal" VerticalOptions="Start">
<!-- Place new controls here -->
<Entry Text="top" x:Name="TopEntry"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
Completed="Entry_Completed" />
</StackLayout>
<StackLayout Orientation="Horizontal" VerticalOptions="End">
<!-- Place new controls here -->
<Entry Text="Bottom" x:Name="BottomEntry"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</StackLayout>
MainPage.xaml.cs
void Entry_Completed(object sender, EventArgs e)
{
BottomEntry.Focus();
}
If you have many more than 2 entries and you want to focus on next entry when press the "done" on keyboard, you can also refer to this.

FindViewById on Xamarin Forms?

I need some way to find View/object by its ID. I heared about FindViewById function, but it's not present in my ContentPage class. Where can I find it?
Context: I have ListView with buttons inside. I don't know how many buttons are there. When user clicks on one of those buttons, I get its ID and store globally. What I want to accomplish is to find this specific button, which id was stored in variable.
<StackLayout x:Name="chooseObjectButtons">
<ListView x:Name="SlotsList" ItemsSource="{Binding .}" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout>
<Button Text="{Binding Text}" BackgroundColor="Gray" Clicked="SlotChosen" />
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
Change the XAML to:
<ListView ItemsSource="{Binding Slots}" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout>
<Button Text="{Binding Title}" BackgroundColor="Gray" Clicked="Handle_Clicked" Command="{Binding Select}" />
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Handle click:
private Button LastButtonClicked;
void Handle_Clicked(object sender, System.EventArgs e)
{
if (LastButtonClicked != null)
{
// Change background here
}
LastButtonClicked = (Button)sender;
// Do stuff here.
}
To process the specific command for each button use:
public List<SlotsButtons> Slots
{
get
{
return new List<SlotsButtons>
{
new SlotsButtons
{
Title = "T1",
Select = new Command(()=>{
// do stuff here when clicked.
})
},
new SlotsButtons
{
Title = "T2",
Select = new Command(()=>{
// do stuff here when clicked.
})
}
};
}
}
NOTE: Initial question answer.
In Xamarin Forms the class ContentPage is a Partial class.
One part is automatically generated from XAML and the other represents the code behind.
The XAML generated Partial class has the code to find the views by name.
The correct name is FindByName and you should't need to use this in your partial class because it its already made in the generated partial class.
If you want to access a view in your code behind just give it a name in XAML.
There is an XAML example:
<Button x:Name="button" ></Button>
And in your code behind you could do something like:
button.BorderWidth = 3;
If you still need to find a view for some reason, do this:
var button = this.FindByName<Button>("button");

Accessing a ProgressBar within a ListBox of buttons

I want to be able to control when I will show a ProgressBar based on a click event. Normally this would be fine, except that I don't believe I can access the ProgressBar since it is so nested in with this structure.
The following code sample shows the structure I Have
<ListBox Name="AudioListBox" Margin="12,0,0,0" Grid.Row="2" Width="396" HorizontalAlignment="Left" ItemsSource="{Binding Audio}">
<ListBox.ItemTemplate>
<DataTemplate>
<Button BorderThickness="0.0" Click="ChapterPlayerButtonClick" Style="{StaticResource ButtonStyle1}">
<StackPanel Name="ButtonsStackPanel" Margin="0,0,0,17">
<TextBlock Foreground="{Binding ChapterForeground}" Text="{Binding LineOne}" TextWrapping="Wrap" Style="{StaticResource PhoneTextLargeStyle}"/>
<ProgressBar x:Name="MyProgressBar" Value="{Binding ChapterProgressPosition}" Visibility="Collapsed"
IsIndeterminate="False" Foreground="{Binding ChapterForeground}" Width="300" Background="Black" HorizontalAlignment="Left">
</ProgressBar>
<TextBlock Text="{Binding LineTwo}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
</StackPanel>
</Button>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
In this example, I want to be able to change the visbility of this progress bar, as well as bind it to update with a timer I have set up. Unfortunately I can't find a way to turn on the visbility for the progress bar on the button click.
This is where MVVM can really help - you've already got a data binding to your ViewModel presumably from looking at your XAML.
You can send a message to your ViewModel to turn on the progress bar, by changing a IsProgressBarVisible property on your ViewModel.
Then you can bind to this boolean in your ViewModel using a VisibilityValueConverter (see post by Jeff Wilcox at this link for more details).
<ProgressBar
x:Name="MyProgressBar"
Visibility="{Binding IsProgressBarVisible, Converter={StaticResource VisibilityConverter}}"
IsIndeterminate="{Binding IsIndeterminate}"
...
</ProgressBar>
If you want to update bound items within the ItemTemplate you'll need to update the bindings as you can't refer to instances of such items by name. (Because you can't have multiple items with the same name.)
In the Click event handler you can access the viewmodel instance via the sender and manipulate the properties there.
For example, the following will increment the value of the progress bar each time the button is tapped/clicked.
private void ChapterPlayerButtonClick(object sender, RoutedEventArgs e)
{
((sender as FrameworkElement).DataContext as ItemVm).ChapterProgressPosition++;
}
Note that due to a "quirk" of the ProgressBar you'll need to enable TwoWay binding to update the Value via binding.
I'm sure you can work out how to do the rest.
You'll need to bind the Visibility if you want to alter that too.
As an alternative solution I'd replace the button click event with a RelayCommand on the ViewModel itself to simplify the code. You could then put all the logic in the same place and not require all the casting as in the click event handler above.

Resources