How to create swipeable ListView renderer in Xamarin UWP - xamarin

I have an application that consists of a TabbedPage that holds custom ContentViews.
In the main ContentView I have a custom ListView, that has a ListViewRenderer in Xamarin UWP.
The ListView items have a template:
<DataTemplate x:Key="ListViewItemTemplate">
<Grid x:Name="grid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<!-- TEXT -->
<TextBlock Grid.Column="0"
Margin="5"
VerticalAlignment="Center"
Foreground="Black"
Text="{Binding ActualText}"
TextWrapping="WrapWholeWords" />
<!-- CC -->
<my:CustomControl Grid.Column="1"
ActualCValue="{Binding ActualValue, Mode=TwoWay}" />
<!-- PICKER -->
<ComboBox x:Name="cboxPicker"
Grid.Column="2"
Width="90"
Margin="3"
VerticalAlignment="Center"
ItemsSource="{StaticResource dataSource}"
SelectedIndex="{Binding ActualValue,
Mode=TwoWay}" />
<!-- SEP -->
<Border Grid.Row="1"
Grid.ColumnSpan="3"
BorderBrush="Gray"
BorderThickness="1" />
</Grid>
</DataTemplate>
Unfortunately, when I try to use swipe, the tabs are not changing.
If I use the built-in Xamarin.Forms ListView with items consisting of an image and text, it works normally.
It might be related to the Button's capturing of the focus (assumption).
What should I change to make my custom ListViewRenderer work with swipe?

As I was using a ListViewRenderer, there was no ListView in the XAML code (it is only provided by the renderer).
The problem however was with the ListView configuration I used in my custom renderer.
I had this:
(Control as SemanticZoom)?.ManipulationMode = Windows.UI.Xaml.Input.ManipulationModes.None;
Now I use this, and the swipe works normally:
(Control as SemanticZoom)?.ManipulationMode = Windows.UI.Xaml.Input.ManipulationModes.System;

Related

Why an Entry control do not receive the input from user in Xamarin Forms?

enter image description hereI want to implement the xamarin essentials map, but with a floating search for the pins that will appear on this map. I'm using a grid to divide the grid's rows and thus use the first row for the map and the second to show a cardview related to the selected pin. I put the search control in row 0 so that it seems to float on the map.
I couldn't get the focus of the search control to work. I don't know if I'm implementing the InputTransparent property correctly.
Any ideas?
<Grid InputTransparent="False">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="140"/>
</Grid.RowDefinitions>
<maps:Map
x:Name="map"
Grid.Column="0"
Grid.Row="0"
Grid.RowSpan="2"
MapType="Street"
HasZoomEnabled="True"
IsShowingUser="True"
InputTransparent="False"
MoveToLastRegionOnLayoutChange="false"
>
</maps:Map>
<StackLayout Grid.Row="0" Grid.Column="0" InputTransparent="True">
<Frame
Margin="20,40,20,0"
Padding="0"
BorderColor="{StaticResource BlackColor}"
CornerRadius="8"
HeightRequest="35">
<Grid VerticalOptions="CenterAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="35" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="35" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="35" />
</Grid.ColumnDefinitions>
<Image
Grid.Row="0"
Grid.Column="0"
HeightRequest="20"
HorizontalOptions="Center"
Source="ic_search_bar"
VerticalOptions="Center"
WidthRequest="20" />
<controls:CustomEntry
x:Name="entrySearch"
Grid.Row="0"
Grid.Column="1"
FontSize="14"
HeightRequest="35"
HorizontalOptions="FillAndExpand"
HorizontalTextAlignment="Start"
Keyboard="Text"
Placeholder="¿Qué se te antoja hoy?"
PlaceholderColor="#979797"
ReturnCommand="{Binding SearchCommand}"
InputTransparent="False"
ReturnType="Search"
Text="{Binding SearchText}"
TextChanged="entrySearch_TextChanged"
VerticalOptions="FillAndExpand"
VerticalTextAlignment="Center" />
<Image
Grid.Row="0"
Grid.Column="2"
HeightRequest="15"
HorizontalOptions="Center"
Source="ic_clear_search.png"
VerticalOptions="Center"
WidthRequest="15">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding ClearSearchCommand}" NumberOfTapsRequired="1" />
</Image.GestureRecognizers>
</Image>
</Grid>
</Frame>
</StackLayout>
</Grid>
I try to use the property in many parts of the code
From the docs on InputTransparent
true if neither the element nor its children should receive input and
should, instead, pass inputs to the elements that are visually behind
the current visual element
Your stackLayout is transparent so it’s children, including the Entry, are also transparent
You might be thinking InputTransparent does the opposite of what it actually does. True makes an area effectively invisible to touch; touch goes through it.
If you want an element to be touchable, it has to be "False". BUT all its ancestors must also NOT BLOCK touch.
If you really mean "True", but you have children you want to click on, do this:
<SomeLayoutNameHere InputTransparent="True" CascadeInputTransparent="False" ...>
That allows children to specify whether they can receive touch (InputTransparent=False), or are invisible to touch (=True).
"False" is the default.

How to set all the item template data into a single view in Xamarin Carousel

I have tried to make all the items in the itemtemplate into a single view as like in the below image, how to achieve this by using Xamarin CarouselView, i am using like this
carousel = new CarouselView();
carousel.BindingContext = this;
carousel.ItemTemplate = itemTemplate;
carousel.SetBinding(CarouselView.ItemsSourceProperty, new Binding(nameof(this.Items), mode: BindingMode.OneWay));
LinearItemsLayout linearItemsLayout = new LinearItemsLayout(ItemsLayoutOrientation.Horizontal);
linearItemsLayout.SnapPointsAlignment = SnapPointsAlignment.Start;
linearItemsLayout.SnapPointsType = SnapPointsType.Mandatory;
carousel.ItemsLayout = linearItemsLayout;
this.Children.Add(carousel,0,1);
Expected UI
The easiest way of doing something like that would be to use the Horizontal CollectionView
CollectionView can display its items in a horizontal list by setting its ItemsLayout property to HorizontalList:
When you check the documents it gives a similar example
<CollectionView ItemsSource="{Binding Monkeys}"
ItemsLayout="HorizontalList">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="35" />
<RowDefinition Height="35" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70" />
<ColumnDefinition Width="140" />
</Grid.ColumnDefinitions>
<Image Grid.RowSpan="2"
Source="{Binding ImageUrl}"
Aspect="AspectFill"
HeightRequest="60"
WidthRequest="60" />
<Label Grid.Column="1"
Text="{Binding Name}"
FontAttributes="Bold"
LineBreakMode="TailTruncation" />
<Label Grid.Row="1"
Grid.Column="1"
Text="{Binding Location}"
LineBreakMode="TailTruncation"
FontAttributes="Italic"
VerticalOptions="End" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
Alternatively, this layout can also be accomplished by setting the ItemsLayout property to a LinearItemsLayout object, specifying the Horizontal ItemsLayoutOrientation enumeration member as the Orientation property value:
<CollectionView ItemsSource="{Binding Monkeys}">
<CollectionView.ItemsLayout>
<LinearItemsLayout Orientation="Horizontal" />
</CollectionView.ItemsLayout>
...
</CollectionView>
This results in a single row list, which grows horizontally as new items are added:

How to change the style of tab in segment control in xamarin forms

I have a segment control where I'm displaying tabs. But I'm not able to edit the style of the tab in Xamarin Forms. This is the UI I want
This is how I want to display my tabs in the segment control. I'm able to change the tint color, background color, and text color but none of that will get me a tab in this style. This is my current UI
This is XAML code where I implemented the segment control
<controls:SegmentedControl BackgroundColor="White" SelectedTextColor="Black" TintColor="#FFA500" x:Name="SegControl" ValueChanged="Handle_ValueChanged">
<controls:SegmentedControl.Children>
<controls:SegmentedControlOption Text="VENDOR NAME" />
<controls:SegmentedControlOption Text="PRODUCT/SERVICE" />
</controls:SegmentedControl.Children>
</controls:SegmentedControl>
<StackLayout x:Name="SegContent" />
</StackLayout>
<StackLayout Margin="0,30,0,0">
<StackLayout AbsoluteLayout.LayoutBounds=".20,1,1,.1" AbsoluteLayout.LayoutFlags="All" BackgroundColor="White" HorizontalOptions="FillAndExpand" Orientation="Horizontal">
<StackLayout Style="{StaticResource ButtonNavigationBarStackLayoutStyle}" x:Name="stckNear">
<Image Margin="0,10,0,10" x:Name="imgNear" Style="{StaticResource ButtonNavigationBarImageStyle}" />
<Label Text="Near" Style="{StaticResource ButtonNavigationBarLabelStyle}"></Label>
</StackLayout>
<StackLayout Style="{StaticResource ButtonNavigationBarStackLayoutStyle}" x:Name="stckSearch">
<Image Margin="0,10,0,10" x:Name="imgSearch" Style="{StaticResource ButtonNavigationBarImageStyle}" />
<Label Text="Search" Style="{StaticResource ButtonNavigationBarLabelStyle}"></Label>
</StackLayout>
<StackLayout Style="{StaticResource ButtonNavigationBarStackLayoutStyle}" x:Name="stckCart">
<Image Margin="0,10,0,10" x:Name="imgCart" Style="{StaticResource ButtonNavigationBarImageStyle}" />
<Label Text="Cart" Style="{StaticResource ButtonNavigationBarLabelStyle}"></Label>
</StackLayout>
<StackLayout Style="{StaticResource ButtonNavigationBarStackLayoutStyle}" x:Name="stckAccount">
<Image Margin="0,10,0,10" x:Name="imgAccount" Style="{StaticResource ButtonNavigationBarImageStyle}" />
<Label Text="Account" Style="{StaticResource ButtonNavigationBarLabelStyle}"></Label>
</StackLayout>
</StackLayout>
I'm not using any custom renderer for this segment control. Do I have to use a custom renderer for implementing the required UI? If yes how? Any suggestions?
SegmentedControl is not a built in Xamarin.Forms control. There are a few libraries that offer a SegmentedControl, so it would help to know which one you are using.
That said, the library author who created that SegmentedControl also made the platform renderers and so the different look on iOS vs Android is a result of that.
You can, of course, create your own custom renderer, but then why use the library?
Easier to me would be to make a control using Xamarin Forms, for instance you can use a grid that has a first row of two labels ( or Buttons) and a second row of 2 BoxViews that can act as the underline (very short height). Then just add TapGestureRecognizers to each Label (or just use a Buttons and style as needed).
Here's an example using Buttons and BoxViews:
XAML:
<Grid Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button x:Name="vBtn"
Text="VENDOR NAME" Clicked="Handle_Clicked"
TextColor="Black"
BackgroundColor="Transparent"
BorderColor="Transparent"
Grid.Row="0"
Grid.Column="0"/>
<Button x:Name="pBtn"
Text="PRODUCT/SERVICE" Clicked="Handle_Clicked"
TextColor="Black"
BackgroundColor="Transparent"
BorderColor="Transparent"
Grid.Row="0"
Grid.Column="1" />
<BoxView x:Name="vBox"
Color="#FFA500" HeightRequest="5"
Grid.Row="1"
Grid.Column="0"/>
<BoxView x:Name="pBox"
Color="Silver" HeightRequest="5"
Grid.Row="1"
Grid.Column="1"/>
</Grid>
Code behind:
void Handle_Clicked(object sender, System.EventArgs e)
{
Button btn = sender as Button;
if (btn.Text == "PRODUCT/SERVICE")
{
vBox.Color = Color.Silver;
pBox.Color = Color.FromHex("#FFA500");
// Do anything else you need to do when the PRODUCT/SERVICE is tapped
}
else
{
vBox.Color = Color.FromHex("#FFA500");
pBox.Color = Color.Silver;
// Do anything else you need to do when the VENDOR NAME is tapped
}
}
No library or custom renderer needed.

Windows Phone 8.1 app ProgressRing not showing

I am trying to show a progressring while storing data but I can not get it to show. My Xaml looks as follows:
<Page
x:Class="MyApp.MyPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MyApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:Model="using:MyApp.Model"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.BottomAppBar>
<CommandBar Height="58">
<AppBarButton Icon="Save" Label="" Click="AddAppBarButton_Click"/>
</CommandBar>
</Page.BottomAppBar>
<Grid x:Name="LayoutRoot">
<Grid.ChildrenTransitions>
<TransitionCollection>
<EntranceThemeTransition/>
</TransitionCollection>
</Grid.ChildrenTransitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Title Panel -->
<StackPanel Grid.Row="0" Margin="19,0,0,0">
<TextBlock Text="Name" Style="{ThemeResource BaseTextBlockStyle}" Margin="0,12,0,0"/>
<TextBox x:Name="nameTextBox" Margin="0,10,21.833,0" />
<TextBlock Text="Item" Style="{ThemeResource BaseTextBlockStyle}" Margin="0,12,-4.167,0"/>
<TextBox x:Name="itemTextBox" Margin="0,10,96.833,0" PlaceholderText="" Grid.ColumnSpan="2" />
<AppBarButton Grid.Column="1" HorizontalAlignment="Left" Icon="AddFriend" Label="" Margin="88.167,-2,0,0" VerticalAlignment="Top" Height="66" Click="ItemAppBarButton_Click"/>
<Grid Margin="0,0,-0.167,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
</Grid>
<ListView x:Name="ItemListView" Height="379" Margin="0,10,21.833,0" IsItemClickEnabled="True" ItemClick="ItemListView_ItemClick">
<ListView.DataContext>
<Model:Person/>
</ListView.DataContext>
</ListView>
</StackPanel>
<ProgressRing Name="BusyProgressRing" HorizontalAlignment="Left" Margin="169,299,0,0" VerticalAlignment="Top"/>
</Grid>
</Page>
When I do:
BusyProgressRing.IsActive = true;
It does not show. Because at the end of my member function I do a BusyProgressRing.IsActive = false; and the rendering of the ring only occurs after my whole function is done.
Does anyone know how to solve this?
Yes, because ProgressRing does not appears in design time. It appears just in Runtime. You will see it when you deploy the application.
Additionally, ProgressRing always appears in the center of the screen. You don't have to write code for this.
Tested your code and the ProgressRing works. I did remove the margins and correct issue with row/column position of some UI element in your code and add
IsActive = "True"
to the ProgressRing. Your original code (with the margins) puts ProgressRing outside visible area when tested on my desktop.

Slow Page loading when using ExpanderView & Binding (Windows Phone 7)

I have a Panorama control, which has an ExpanderView Item (from Silverlight toolkit).
My client wants this page to be customizable. Thats why I created 3 level of binding:
The PanoramaItems, the ExpanderView headers and the ExpanderView content.
The problem when I set the itemssource of the Panorama control. it takes about 5 seconds to show the items.
Any idea how I can solve this?
C# code:
private void panorama_Loaded(object sender, RoutedEventArgs e)
{
this.DataContext = App.Products;
}
XAML Code:
<controls:Panorama Loaded="panorama_Loaded" x:Name="panorama" ItemsSource="{Binding}">
<controls:Panorama.ItemTemplate>
<DataTemplate>
<ListBox ItemsSource="{Binding Sub_Products}" >
<ListBox.ItemTemplate>
<DataTemplate>
<toolkit:ExpanderView Header="{Binding}" Expander="{Binding}" ItemsSource="{Binding Sub_Sub_Products}">
<toolkit:ExpanderView.ExpanderTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image VerticalAlignment="Center" Source="Images/List.png" Width="25" />
<TextBlock Text="{Binding Title}" />
</StackPanel>
</DataTemplate>
</toolkit:ExpanderView.ExpanderTemplate>
<toolkit:ExpanderView.ItemTemplate>
<DataTemplate>
<Grid Margin="-30,0,0,0" Background="White" Width="450" Tap="Grid_Tap" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Image Grid.Row="0" Source="{Binding ImageSource}" />
<StackPanel VerticalAlignment="Top" Grid.Column="1">
<TextBlock Text="{Binding Title}" />
<TextBlock Text="{Binding Description}" />
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
</Grid>
<TextBlock Margin="0,12,32,0" Grid.Row="1" Text="Learn more" />
</StackPanel>
</Grid>
</DataTemplate>
</toolkit:ExpanderView.ItemTemplate>
</toolkit:ExpanderView>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</controls:Panorama.ItemTemplate>
</controls:Panorama>
You could try to collapse the panorama items that are off screen and only set visibility to visible on demand. That should at least reduce the size of the visible tree.
A good way to find the slow parts is to use the profiler in Visual Studio. You will find one frame which is really slow (it will have a render time of 5 seconds in your case). Then dig into the visual tree of that frame and see which elements took a long time to render and try to optimize these.
Remove the ExpanderView ItemsSource binding in xaml and bind to it when the Expander is manupulated in code. Just leave it as ItemsSource="{Binding}". That way you will dynamically build you visual tree as the user taps on the expander.
The event handler is something like below. I am assuming Product is the type in your App.Products list. Also ensure that you hook up the event in your xaml for the expander.
private void ExpanderView_ManipulationStarted(object sender, System.Windows.Input.ManipulationStartedEventArgs e)
{
var expander = sender as ExpanderView;
expander.ItemsSource = (expander.DataContext as Product).Sub_Sub_Products;
}
Hope this solves your slow loading issues and is not too late at this time.

Resources