CollectionView rowspacing - maui

I try to use a CollectionView to display simple tabular text.
It seems like the (visual) minimum spacing between rows in a CollectionView is quite large.
In my case I'm using some Labels within a DataTemplate, all with default values (except for the bindings of text of course) with default font size and the visually empty (valuable screen surface) is close to twice the height of the characters in the text.
Is it possible to make such a tabular view denser?
(Not necessarily by a CollectionView, but any View which is capable of displaying such data)
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:vm="clr-namespace:MauiApp1.ViewModels" x:Class="MauiApp1.MainPage" Title="MainPage">
<ContentPage.BindingContext>
<vm:CollectionViewModel/>
</ContentPage.BindingContext>
<Grid>
<CollectionView VerticalScrollBarVisibility="Always" SelectionMode="Multiple" ItemsSource="{Binding Items}" BackgroundColor="Black">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid ColumnDefinitions="150,150,*">
<Label TextColor="White" Grid.Column="0" Text="{Binding Name}" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
</ContentPage>

Related

Can You Scale the Content of a WebView Control to Fit the Container

I'm using a WebView control on a page in my MAUI app and I would like the content of the page (a video) to scale to fit the container size. Currently it spills over and it's not obvious (or useful really) that a user would have to scroll the video up and down and side to see it. Can the content be scaled to fit the container dimensions?
Here's a short example based on standard new .MAUI project. This is the page markup:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiApp2.MainPage">
<Grid
x:Name="MainGrid"
RowDefinitions="50,*"
ColumnDefinitions="*">
<Button
Grid.Row="0"
Grid.Column="0"
x:Name="CounterBtn"
HeightRequest="40"
Text="Click me"
Clicked="OnCounterClicked"
HorizontalOptions="Center" />
<VerticalStackLayout
Grid.Row="1"
Grid.Column="0"
Spacing="25"
Padding="30,0">
<Border
Grid.Row="1"
Grid.Column="0"
Grid.RowSpan="3"
Stroke="Black"
StrokeThickness="3"
x:Name="WebBorder">
<Border.StrokeShape>
<RoundRectangle CornerRadius="5" />
</Border.StrokeShape>
<VerticalStackLayout
BackgroundColor="White">
<Image
x:Name="CloseBtn"
Margin="5,5,0,0"
HorizontalOptions="Start"
Source="close_button.png">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="CloseButton_Clicked"/>
</Image.GestureRecognizers>
</Image>
<WebView
x:Name="WebView"/>
</VerticalStackLayout>
</Border>
</VerticalStackLayout>
</Grid>
</ContentPage>
The only thing I don't have for you (since I can't add an attachment) is the close button png file. This is stuff added to the code behind:
private async void OnCounterClicked(object sender, EventArgs
e)
{
//display the container
WebView.IsVisible= true;
WebView.HeightRequest =
DeviceDisplay.Current.MainDisplayInfo.Height - 60;
WebView.WidthRequest =
DeviceDisplay.Current.MainDisplayInfo.Width - 20;
WebView.Margin = new Thickness(5, 0, 5, 0);
//show the video
WebView.Source =
"https://www.youtube.com/shorts/JSIqFdb4KQ8";
WebView.HeightRequest = WebView.HeightRequest -
CloseBtn.Height - 10;
for (int i = 0; i < 2; i++)
{
await CloseBtn.RotateTo(180, 200);
await CloseBtn.RotateTo(0, 200);
}
}
private void CloseButton_Clicked(object sender, EventArgs e)
{
//hide it a
WebView.IsVisible= false;
}
When the video plays it is much larger than the viewport of the device. I'm looking for a method or way to scale the content contained in the WebView to be 100% of the WebView's size.
Do you mean the space of the VerticalStackLayout of your code?
I tried to remove the Padding and Spacing of the VerticalStackLayout in your code,then there is no such problem.
Spacing="25"
Padding="30,0"
You can refer to the following code I tested on my side:
<Grid
x:Name="MainGrid"
BackgroundColor="Red"
RowDefinitions="50,*"
ColumnDefinitions="*"
>
<Button
Grid.Row="0"
Grid.Column="0"
x:Name="CounterBtn"
HeightRequest="40"
Text="Click me"
HorizontalOptions="Center" />
<VerticalStackLayout
Grid.Row="1"
Grid.Column="0"
BackgroundColor="Blue">
<Border
Grid.Row="1"
Grid.Column="0"
Grid.RowSpan="3"
Stroke="Black"
StrokeThickness="3"
x:Name="WebBorder">
<Border.StrokeShape>
<RoundRectangle CornerRadius="5" />
</Border.StrokeShape>
<VerticalStackLayout
BackgroundColor="White">
<Image
BackgroundColor="Yellow"
x:Name="CloseBtn"
Margin="5,5,0,0"
HorizontalOptions="Start"
Source="dotnet_bot.svg">
</Image>
<!--<WebView
x:Name="WebView"/>-->
<WebView HorizontalOptions="FillAndExpand" VerticalOptions="CenterAndExpand" Source="https://dotnet.microsoft.com/apps/xamarin" />
</VerticalStackLayout>
</Border>
</VerticalStackLayout>
</Grid>

Correct AbsoluteLayout positioning/overlay

The main goal of the task to create AutoSuggest control.
In my case AutoSuggest control is custom control inherited from Grid
<Grid xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
...
xmlns:handlers ="clr-namespace:CrowdExchangeV2.Controls.Handlers"
WidthRequest="150">
<Grid.RowDefinitions>
<RowDefinition Height="35"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Frame Grid.Row="0"
...>
<handlers:BorderlessEntry Placeholder="{Binding Source={x:Reference this}, Path=Placeholder}"
WidthRequest="150"
.../>
</Frame>
<AbsoluteLayout
WidthRequest="150"
MaximumHeightRequest="100"
Grid.Row="1"
x:Name="resAl">
<ScrollView
MaximumHeightRequest="100"
MaximumWidthRequest="160"
x:Name="resSV">
<CollectionView x:Name="list">
<CollectionView.ItemTemplate>
<DataTemplate>
<HorizontalStackLayout VerticalOptions="Center"
HorizontalOptions="Start">
<Label Text="{Binding Key}" Padding="0,0,4,0"/>
<Label Text="{Binding Value}"/>
</HorizontalStackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</ScrollView>
</AbsoluteLayout>
</Grid>
So, control looking for suggestions in Dictionary while user typing text in Entry. The thing is - when CollectionView updates suggestions it pushes all the other elements on ContentPage down... but suppose to overlay them. All right lets wrap Suggester in AbsoluteLayout on contentPage and setBounds to a desirable position. (PS: Suggester name is suggester 0_o)
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
...
Title=" ">
<AbsoluteLayout x:Name="mainAbs">
<AbsoluteLayout Margin="0,0,0,0"
x:Name="suggestAl">
<suggester:Suggester Placeholder="USD"
SearchDictionary="{Binding SearchCurrency}"
MaximumHeightRequest="150"
MaximumWidthRequest="150"/>
</AbsoluteLayout>
<Grid Padding="10" AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="All">
<ScrollView>
<VerticalStackLayout>
...
<Frame HorizontalOptions="Fill">
<VerticalStackLayout>
...
<VerticalStackLayout HeightRequest="80"
x:Name="currVSL">
<Label Text="Currency out:"
VerticalOptions="Start"
HorizontalOptions="Start"
FontSize="Header"
x:Name="curLbl"/>
**SUggester should be here**
</VerticalStackLayout>
</VerticalStackLayout>
</Frame>
</VerticalStackLayout>
</ScrollView>
</Grid>
</AbsoluteLayout>
</ContentPage>
The first idea is - to grab x:Name="currVSL" bounds, adjust it for size of Label, and place x:Name="suggestAl" there, but i cant get absolute position of x:Name="currVSL" only relative and in absolute terms it's wrong
I don't want to hardcode position in static numbers, because the position highly depends on a particular device.
So the question is how to achieve a desirable result - Place x:Name="currVSL" under the x:Name="curLbl" label.
OR
Might be there is a more elegant solution to show suggestion results without pushing all the other elements down?(Read:overlay other elements on UI)
Image to visualise UI

How to change position of the app title in .NET MAUI?

I want to change the position of title to the middle or right side of the screen. I used the following code:
<Shell
x:Class="CostManagement.AppShell"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:CostManagement"
Shell.FlyoutBehavior="Disabled"
FlowDirection="RightToLeft">
<ShellContent
Title="Main Page"
ContentTemplate="{DataTemplate local:MainPage}"
Route="MainPage" />
</Shell>
How can I change its position?
This can be customized by setting the Shell.FlyoutContent and use the CollectionView to define the appearance of the menu item like the title as you said. You can refer to the code sample below:
<?xml version="1.0" encoding="UTF-8" ?>
<Shell
x:Class="CostManagement.AppShell"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:CostManagement"
FlyoutBackgroundColor="LightGray"
FlyoutBehavior="Flyout"
FlyoutWidth="400"
FlyoutHeight="400">
<Shell.FlyoutContent>
<CollectionView BindingContext="{x:Reference shell}" ItemsSource="{Binding FlyoutItems}" IsGrouped="True">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid ColumnDefinitions="40,*" Padding="10">
<Image Source="{Binding Icon}"></Image>
<Label Grid.Column="1" Text="{Binding Title}" TextColor="Black"></Label>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Shell.FlyoutContent>
</Shell>

TapGestureRecognition in Xamarin Forms Listview

I need to check if the empty part of a Xamarin Forms Listview is tapped. For example, there are 5 rows and the space below those filled rows is tapped a method should be called.
I tried adding Tapgesturerecognizer to the Listview and the page containing the listview but this didnt work.
Is there a way to check if someone tapped the empty space in the listview?
<ListView x:Name="ItemsListView"
ItemsSource="{Binding Items}"
VerticalOptions="FillAndExpand"
HasUnevenRows="true"
RefreshCommand="{Binding LoadItemsCommand}"
IsPullToRefreshEnabled="true"
IsRefreshing="{Binding IsBusy, Mode=OneWay}"
CachingStrategy="RecycleElement"
ItemSelected="OnItemSelected">
<d:ListView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>First Item</x:String>
<x:String>Second Item</x:String>
<x:String>Third Item</x:String>
<x:String>Fourth Item</x:String>
<x:String>Fifth Item</x:String>
<x:String>Sixth Item</x:String>
</x:Array>
</d:ListView.ItemsSource>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="10">
<Label Text="{Binding Text}"
d:Text="{Binding .}"
LineBreakMode="NoWrap"
Style="{DynamicResource ListItemTextStyle}"
FontSize="16" />
<Label Text="{Binding Description}"
d:Text="Item descripton"
LineBreakMode="NoWrap"
Style="{DynamicResource ListItemDetailTextStyle}"
FontSize="13" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.GestureRecognizers>
<TapGestureRecognizer Tapped="OnTapGestureRecognizerTapped" NumberOfTapsRequired="1"></TapGestureRecognizer>
</ListView.GestureRecognizers>
</ListView>
Try to adding footer to the Listview
<ListView
x:Name="ItemsListView"
...>
<ListView.Footer>
<ContentView>
<ContentView.GestureRecognizers>
<TapGestureRecognizer />
<ContentView.GestureRecognizers>
</ContentView>
</ListView.Footer>
</ListView>
set footer view and place your TapGestureRecognizer
Checkout this https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/listview/interactivity#selection-and-taps.
it discusses the selection activity in the ListView so u can execute some logic When an item is selected
Update:
Remove Code in the Screenshot then configure the ListView item selection as shown in the link.
then put the ListView (make sure that the list view fill only the space it needs) In a StackLayout and Configure the Tapped event of the stackLayout with the logic u need to execute on clicking the empty page.

Select ListView Element on button Click using MVVM

I have one list as RoomGroupList and another as RooList,One Room Group have multiple Roos in it, like
RoomGroup 1 => Room-1
Room-2
Room-3
I have bound RoomGroupList to ListView and RoomGroupControll is Generating From it as,
<ListView x:Name="lstRoomGroupList" SelectionMode="Single" ItemsSource="{Binding roomGroupList,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding evokoRoomGroup,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
<ListView.ItemTemplate>
<DataTemplate>
**<UserConrols:RoomGroupControl/>**
</DataTemplate>
</ListView.ItemTemplate
Now RoomGroupControl has one ListView to Listout No.ofRooms in it as,
<ListView x:Name="lstRoomList" Grid.Row="3" ItemsSource="{Binding GetroomList,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
SelectedValue="{Binding DataContext.EvokoRoom,ElementName=tbDashBoard,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
HorizontalAlignment="Stretch" VerticalAlignment="Top" Background="#F3F3F5"
BorderBrush="LightGray" BorderThickness="0"
Margin="0,0,0,0" Height="Auto" MaxHeight="200" ScrollViewer.VerticalScrollBarVisibility="Visible">
<ListView.ItemTemplate>
<DataTemplate>
**<UserConrols:RoomControl/>**
</DataTemplate>
</ListView.ItemTemplate>
what I want is,when I click on any button from ListElements at that time it's corresponding ListItem(row) should be selected so that I have added EventSetter using Resource on RoomGroupList as
<ListView.Resources>
<Style TargetType="{x:Type ListViewItem}">
<EventSetter Event="PreviewGotKeyboardFocus" Handler="SelectCurrentItem"/>
</Style>
</ListView.Resources>
It's working properly for RoomGroupList I'm able to select Different Groups but Problem is I Can't select Rooms From RoomGroup which I have selected.
If anyone knows how to manage this, can also provide me Links and Suggestions,Thanks.