Xamarin dynamic grid layout - c#

I have a collection of objects that has a property like "ValueType", based on this property I invoke a DataTemplateSelector class that would return type of control to be displayed for that object.
<control:ControlDataTemplateSelector x:Key="personDataTemplateSelector"
RangeTemplate="{StaticResource rangeControl}"
EnumTemplate="{StaticResource pickControl}"
DateTemplate="{StaticResource dateControl}"/>
<DataTemplate x:Key="rangeControl">
<ViewCell>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<control:ScreenLabel Grid.Row="0" Grid.Column="{Binding Path=SortOrder, Converter={StaticResource sortOrderToColIndexConverter}}" Text="{Binding Path=TraitDescription}" />
<Entry Grid.Row="1" Grid.Column="{Binding Path=SortOrder, Converter={StaticResource sortOrderToColIndexConverter}}" />
</Grid>
</ViewCell>
</DataTemplate>
<DataTemplate x:Key="dateControl">
<ViewCell>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<control:ScreenLabel Grid.Row="0" Grid.Column="{Binding Path=SortOrder, Converter={StaticResource sortOrderToColIndexConverter}}" Text="{Binding Path=TraitDescription}" />
<DatePicker Grid.Row="1" Grid.Column="{Binding Path=SortOrder, Converter={StaticResource sortOrderToColIndexConverter}}"></DatePicker>
</Grid>
</ViewCell>
</DataTemplate>
<DataTemplate x:Key="pickControl">
<ViewCell>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<control:ScreenLabel Grid.Row="0" Grid.Column="{Binding Path=SortOrder, Converter={StaticResource sortOrderToColIndexConverter}}" Text="{Binding Path=TraitDescription}" />
<Picker Grid.Row="1" Grid.Column="{Binding Path=SortOrder, Converter={StaticResource sortOrderToColIndexConverter}}" />
</Grid>
</ViewCell>
</DataTemplate>
I am having issue displaying these in grid with two column format, for example if there are 9 objects in the collection need to display a tabular view with 4 rows of 2 columns each and a 5th row that has one column.
With my current code, i get a zig zag kind of layout. But I need Like thisNeed some suggestions
Am looking for solution that would need to work in iOS and Droid

I would use StackLayouts instead of Grids inside of your ViewCells.
You can do:
<StackLayout VerticalOptions="FillAndExpand" >
<control:ScreenLabel Text="{Binding Path=TraitDescription}" />
<Entry />
</StackLayout>
Are you sure your Bindings are coming back properly? I haven't seen a comma separated Markup Extension setting on attribute.

Any one looking for answer, we resolved it by using FLowlist view control. It provides options to have side-by-side view

Related

Xamarin Forms, How to favorite Item using ListView

I am making an app I want to add an item in the list view like favorite .I was wondering if some one have an procedure that I can use o see or and example of what I need.
Thanks
Please help on this im new to Xamarin forms.
In your listview, you can use Xamarin.Forms SwipeView to achieve this function.
The SwipeView is a container control that wraps around an item of content, and provides context menu items that are revealed by a swipe gesture:
You can refer to the follownng code:
<CollectionView x:Name="collectionView"
ItemsSource="{Binding Monkeys}">
<CollectionView.ItemTemplate>
<DataTemplate>
<SwipeView>
<SwipeView.LeftItems>
<SwipeItems>
<SwipeItem Text="Favorite"
IconImageSource="favorite.png"
BackgroundColor="LightGreen"
Command="{Binding Source={x:Reference collectionView}, Path=BindingContext.FavoriteCommand}"
CommandParameter="{Binding}" />
<SwipeItem Text="Delete"
IconImageSource="delete.png"
BackgroundColor="LightPink"
Command="{Binding Source={x:Reference collectionView}, Path=BindingContext.DeleteCommand}"
CommandParameter="{Binding}" />
</SwipeItems>
</SwipeView.LeftItems>
<Grid BackgroundColor="White"
Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Image Grid.RowSpan="2"
Source="{Binding ImageUrl}"
Aspect="AspectFill"
HeightRequest="60"
WidthRequest="60" />
<Label Grid.Column="1"
Text="{Binding Name}"
FontAttributes="Bold" />
<Label Grid.Row="1"
Grid.Column="1"
Text="{Binding Location}"
FontAttributes="Italic"
VerticalOptions="End" />
</Grid>
</SwipeView>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
The key code in MonkeysViewModel.cs is:
public ICommand FavoriteCommand => new Command<Monkey>(FavoriteMonkey);
void FavoriteMonkey(Monkey monkey)
{
monkey.IsFavorite = !monkey.IsFavorite;
}
Note:
Though it is used in CollectionView, but the usage in listView is similar.
You can get the full sample here:https://github.com/xamarin/xamarin-forms-samples/tree/main/UserInterface/CollectionViewDemos
Please focus on page :
VerticalListSwipeContextItemsPage.xaml .

UWP TabView OneWay x:Bind does not update

I have a TabView whose ItemTemplate is like this:
<controls:TabView.ItemTemplate>
<DataTemplate x:DataType="data:Playlist">
<local:HeaderedPlaylistControl
IsPlaylist="True"
Loaded="HeaderedPlaylistControl_Loaded"
MusicCollection="{x:Bind Mode=OneWay}" />
</DataTemplate>
</controls:TabView.ItemTemplate>
This is part of the HeaderedPlaylistControl:
<local:PlaylistControl
AllowReorder="False"
AlternatingRowColor="True"
ItemsSource="{x:Bind MusicCollection.Songs, Mode=OneWay}">
<local:PlaylistControl.Header>
<controls:ScrollHeader Mode="Sticky">
<UserControl>
<Grid
x:Name="PlaylistInfoGrid"
Padding="10"
Background="{ThemeResource SystemColorHighlightColor}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image
x:Name="PlaylistCover"
Grid.RowSpan="3"
Width="180"
Height="180"
Margin="20"
Source="Assets/monotone_bg_wide.png" />
<TextBlock
x:Name="PlaylistNameTextBlock"
Grid.Column="1"
Margin="0,5"
VerticalAlignment="Center"
FontSize="36"
Foreground="White"
Style="{StaticResource HeaderTextBlockStyle}"
Text="{x:Bind MusicCollection.Name, Mode=OneWay}" />
<TextBlock
x:Name="PlaylistInfoTextBlock"
Grid.Row="1"
Grid.Column="1"
Margin="0,5"
VerticalAlignment="Top"
Foreground="White"
Text="{x:Bind MusicCollection.Songs, Converter={StaticResource SongCountConverter}, Mode=OneWay}" />
</Grid>
</UserControl>
</controls:ScrollHeader>
</local:PlaylistControl.Header>
</local:PlaylistControl>
When I switch between tabs, the HeaderedPlaylistControl doesn't update it's content. Why is that?
Is it because of the MusicCollection property (it is of type Playlist) doesn't notify the binding when switching tabs? If so, where should I put the notification? The definition of Playlist is here.
HeaderedPlaylistControl is here:
Yes, as you suspected, the problem is that the MusicCollection property is an ordinary property which does not notify about changes. To make your code work, you need to make the MusicCollection property a dependency property (see docs). This is a kind of properties which are best for data-bound properties of visual controls and have many additional features as well.
public static readonly DependencyProperty MusicCollectionProperty =
DependencyProperty.Register(
nameof(MusicCollection), typeof(Playlist),
typeof(HeaderedPlaylistControl), null
);
public Playlist MusicCollection
{
get { return (bool)GetValue(MusicCollectionProperty); }
set { SetValue(MusicCollectionProperty, value); }
}

Excessive space in the ListView on Xamarin

i am using Xamarin to realize a listView that is filled dynamically with a list of object.
The main problem is that even i use a static list of 2 elements (for example) there is, in the view, a blank space belonging the listView.
The inherent code is the following:
SfidePage.xaml
<ListView
Grid.Row="2"
x:Name="sfideLanciate"
HasUnevenRows="true"
SeparatorVisibility="None"
>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid
BackgroundColor="{StaticResource OpzioniTitleBackgroundColor}"
Margin="0,1,0,0"
RowSpacing="0"
ColumnSpacing="10"
VerticalOptions="Start"
Padding="5"
>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="7*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<ci:CircleImage Source="avatar" Aspect="AspectFill"
HorizontalOptions="Center" VerticalOptions="Start"
HeightRequest="70" WidthRequest="70"
BorderColor="{StaticResource OpzioniLineDividerBackground}" BorderThickness="3"
Grid.Row="0"></ci:CircleImage>
<Grid RowSpacing="0" ColumnSpacing="0" Grid.Column="1" Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Text="In attesa di Kyle Cain" FontSize="16" Grid.Row="0" TextColor="Black" FontAttributes="Bold"></Label>
<Label Text="Ardeatina Roma 70" Grid.Row="1" TextColor="Black"></Label>
<Label Text="10 DOMANDE - Argomento: Pannelli integrativi" Grid.Row="2" TextColor="{StaticResource LightGreyInfo}"></Label>
</Grid>
<Label Text="1h" Grid.Column="2" Grid.Row="0" TextColor="{StaticResource LightGreyInfo}" HorizontalTextAlignment="Center"></Label>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
SfidePage.xaml.cs
public partial class SfidePage : ContentPage
{
public SfidePage ()
{
InitializeComponent ();
sfideLanciate.ItemsSource = new List<int> { 1, 2 };
}
}
The output is the following:
https://i.imgur.com/jQ40JCr.png
"SFIDE COMPLETATE" is a Stack Layout after the listView, so the blank space is part of the listView.
How can i adapt the height of listView to its elements?
It might be related to the padding property, have you tried removing it?
Also, you set the Margin-Top as 1, this could probably create the Space too.
You set the top margin to 1 in your code: Margin="0,1,0,0" change that to Margin="0" and the space should be gone...
In the Listview, add and set the property "HasUnevenRows = true".
If it doesn't have that property it doesn't bind items to the uneven rows, but still displays them as blank rows.

CarouselView not showing the data

I am trying to display a CarouselView inside a TabbedPage. I already added the (prerelease-)packages to the Project. Here is my xaml file:
<control:CarouselView x:Name="CVMain"
HeightRequest="150" >
<control:CarouselView.ItemTemplate>
<DataTemplate>
<Label HorizontalOptions="Center"
Text="Just a test :)"
VerticalOptions="Center" />
</DataTemplate>
</control:CarouselView.ItemTemplate>
</control:CarouselView>
(control: xmlns:control="clr-namespace:Xamarin.Forms;assembly=Xamarin.Forms.CarouselView")
The label doesn't show up when I launch my app. The carousel still exists tho, I can confirm that by adding the BackgroundColor="Green"attribute to the CarouselView.
What am I missing?
Edit: As suggested, I placed the Label inside a Grid, but without any success (I also added an Image):
<control:CarouselView x:Name="CVMain" HeightRequest="150">
<control:CarouselView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image Grid.RowSpan="2"
Aspect="AspectFill"
Source="{Binding ImageBase64,
Converter={StaticResource Base64ToImageConverter}}" />
<StackLayout Grid.Row="1">
<Label Text="Test123" />
</StackLayout>
</Grid>
</DataTemplate>
</control:CarouselView.ItemTemplate>
</control:CarouselView>

Design Xaml grid with height = 100% and minimum row height size

Here's the problem. I have a grid with some data written in xaml:
<ItemsControl x:Name="ItemsControl" ItemsSource="{Binding Path=MyObjectCollection, UpdateSourceTrigger = PropertyChanged}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Width="Auto">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="27"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" MaxHeight="75" MinHeight="30"></RowDefinition>
</Grid.RowDefinitions>
<Label Name="LabelNumber" Content="{Binding ObjectID}" Grid.Column="0" Style="{StaticResource MyStyleLabel}" />
<control:FocusMeterControl x:Name="HorizontalFocusMeterControl" Value="{Binding ObjectProperty}" Height="Auto" Grid.Column="1" />
<Button Name="RemoveObject" Content="-" Grid.Column="2" Margin="5,0,0,0" Click="ButtonBase_OnClick" Tag="{Binding Point}" Style="{StaticResource MyStyleButton}" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
As you can see I'm creating a new grid for each member in my "MyObjectCollection". Ideally I think I should just create one row instead since this would make my next problem - the real problem easier.
However, I have not found any good way to do this in xaml if even possible. Is this possible without populating the collection manually from c# and setting a row-property in my objects manually in order to do something like this
<Label Name="LabelNumber" Grid.Row="{Binding ManuallyCalculatedRowID}" ... />
My primary problem is that I would like the grid/rows to all be equally high and if possible fill out the parent window. If the parent window is way too large MaxHeight should apply and I would just like some empty space below.
The parent control is a Windows Form ElementHost if that makes any difference.
Please let me know if you need any additional info.
To make all rows of equal hight we can use ItemsPanelTemplate and set it to UniformGrid that will take care of equal sizing problem:
<ItemsControl x:Name="ItemsControl" ItemsSource="{Binding Path=MyObjectCollection, UpdateSourceTrigger = PropertyChanged}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="1" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Width="Auto">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="27"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<Label Name="LabelNumber" Content="{Binding ObjectID}" Grid.Column="0" Style="{StaticResource MyStyleLabel}" />
<control:FocusMeterControl x:Name="HorizontalFocusMeterControl" Value="{Binding ObjectProperty}" Height="Auto" Grid.Column="1" />
<Button Name="RemoveObject" Content="-" Grid.Column="2" Margin="5,0,0,0" Click="ButtonBase_OnClick" Tag="{Binding Point}" Style="{StaticResource MyStyleButton}" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Note that I removed row definition in ItemTemplate to lift vertical size restrictions for items. Not sure if that answers your question but that can be good starting point on the road to solution.

Categories