In Xamarin forms I want to use an image ( png file ) I created as background for a side "hamburger" menu. For example, here is some menu:
Two questions:
1) What's the best image size to use for the menu background
2) How do I put a ListView that contains my menu options on top of the background image ?
I tried using the grid but wasn't successful at stacking them. Code below is a quick summary of how the MasterDetailPage is structured.
//Menu
<MasterDetailPage.Master>
<ContentPage>
<ContentPpage.Content>
<AbsoluteLayout> //Also tried FlexLayout and RelativeLayout
<Image Source="blah" Aspect="Fill"/>
<Grid>
<ListView/>
</Grid>
</AbsoluteLayout>
</ContentPpage.Content>
<ContentPage>
</MasterDetailPage.Master>
//Page content
<MasterDetailPage.Detail>
<ContentPage>
///Page content
</ContentPage>
</MasterDetailPage.Detail>
The goal is to get the side menu looking something like this:
I just tried one sample solution. This is my master page :
<?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:local="using:MasterDetailPageNavigation"
x:Class="MasterDetailPageNavigation.MasterPage"
Padding="0,40,0,0"
Icon="hamburger.png"
Title="Personal Organiser">
<Grid>
<Image Source="Default-Portrait.png" Aspect="AspectFill" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"/>
<StackLayout Margin="0,20,0,0">
<ListView x:Name="listView" x:FieldModifier="public" BackgroundColor="Transparent">
<ListView.ItemsSource>
<x:Array Type="{x:Type local:MasterPageItem}">
<local:MasterPageItem Title="Contacts" IconSource="contacts.png" TargetType="{x:Type local:ContactsPage}" />
<local:MasterPageItem Title="TodoList" IconSource="todo.png" TargetType="{x:Type local:TodoListPage}" />
<local:MasterPageItem Title="Reminders" IconSource="reminders.png" TargetType="{x:Type local:ReminderPage}" />
</x:Array>
</ListView.ItemsSource>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Padding="5,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Source="{Binding IconSource}" />
<Label Grid.Column="1" Text="{Binding Title}" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</Grid>
</ContentPage>
There is a trick to have Grid as a parent. If you put 2 controls in same Cell it will overlap. Here my background image "Default-Portrait" will get overlapped by my StackLayout (listview) which has Background Color set as "Transparent".
For the Size of the Image, I would use multiple Size and put those images in the appropriate drawable-hdpi directory in android and iOS assets.
Let me know if you need any more clarifications.
This is a result:
Related
I have set ViewModel from code behind for Dependency Injection. I would like to leave possibility for IntelliSense suggestions in xaml. Everything seems to work, but once I am adding x:DataType="viewModels:HomeViewModel", I am getting an error for Number property not found and not able to run my solution. Why so and how to fix this?
If I delete x:DataType="viewModels:HomeViewModel", everything works fine.
HomePage.xaml:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyApp.Pages.HomePage"
xmlns:viewModels="clr-namespace:MyApp.ViewModels"
x:DataType="viewModels:HomeViewModel"
Title=""
NavigationPage.HasNavigationBar="False">
<Frame>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Label Grid.Row="0"></Label>
<ListView ItemsSource="{Binding TotalData}" Grid.Row="1">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Padding="5">
<Label Text="{Binding Number}" Margin="0,0,10,0"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Frame>
</ContentPage>
EDIT:
Based on Jason answer my HomePage.xaml should have been:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyApp.Pages.HomePage"
xmlns:viewModels="clr-namespace:MyApp.ViewModels"
xmlns:models="clr-namespace:MyApp.Models"
x:DataType="viewModels:HomeViewModel"
Title=""
NavigationPage.HasNavigationBar="False">
<Frame>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Label Grid.Row="0"></Label>
<ListView ItemsSource="{Binding TotalData}" Grid.Row="1">
<ListView.ItemTemplate>
<DataTemplate x:DataType="models:DataModel">
<ViewCell>
<Grid Padding="5">
<Label Text="{Binding Number}" Margin="0,0,10,0"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Frame>
</ContentPage>
when you add
x:DataType="viewModels:HomeViewModel"
to the page, VS assumes that this applies to the entire page. It is currently not "smart" enough to recognize that there is a templated control in the page that will have a different DataType
There are two ways to address this. One, you can just remove DataType entirely. It is not required, and is just a helper that VS uses to provide Intellisense to the XAML bindings
Alternatively, you can add another DataType to your templated controls that tell VS what types are being used for those controls.
<DataTemplate x:DataType="viewModels:MyModelClass">
you will need to use the correct xmlns and class name for your code
I'm developing a mobile application and I want to put one Grid in the SrollView, under it a ListView with the height of its elements, under the ListView another ListView with same height.
I put two Listviews in StackLayout. It should look something like that
This is content that should scroll in ScrollView
But with this implementation(code below), the first ListView Occupies the entire remaining height, and the second Listview is far from it
there is listview height at the full remaining size
And my second Listview after scrolling is far away, here
It also occupies the entire height of the scrollview
Here is the code:
<ScrollView>
<Grid RowSpacing="2">
<Grid.RowDefinitions>
<RowDefinition Height="130"/>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid x:Name="RecommendedCaloriesGrid" Grid.Row="0" RowSpacing="2" ColumnSpacing="1"
BackgroundColor="Violet" Margin="3">
// here is code of my Grid 1
</Grid>
</Grid>
<StackLayout Grid.Row="1"> // here I want to make a listview under Each other
<ListView x:Name="ItemsListView" BackgroundColor="red"
ItemsSource="{Binding Items}"
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:Array>
</d:ListView.ItemsSource>
<ListView.Header>
<StackLayout Margin="5" Spacing="2">
<StackLayout Orientation="Horizontal">
<Label Text="Завтрак" HorizontalOptions="StartAndExpand"
FontSize="Large" FontAttributes="Bold"/>
<Label Text="744 ккал" HorizontalOptions="EndAndExpand"
FontSize="Large" FontAttributes="Bold"/>
</StackLayout>
<Label Text="Рекомендуется 30% от суточного потребления (n ккал)." FontSize="11"/>
</StackLayout>
</ListView.Header>
<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>
<ListView x:Name="LunchListView" // second ListView under first
ItemsSource="{Binding Items}"
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>Forth Item</x:String>
</x:Array>
</d:ListView.ItemsSource>
// SAME logic here
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</Grid>
</ScrollView>
How I can fix it?
Please help me to find a solution.
I read many articles like below, but did not find the answer. I want to do this without calculating the height in code-behind:
Xamarin.Forms ListView size to content?
Xamarin.Forms - ListView change height at runtime
https://forums.xamarin.com/discussion/comment/66248
Xamarin.Forms: ListView inside StackLayout: How to set height?
Why did you use two listviews to do this, you can just use different DataTemplate to achieve this function.
You can refer to the following code:
1.Consuming a DataTemplateSelector in XAML
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-
namespace:Selector;assembly=Selector" x:Class="Selector.HomePage">
<ContentPage.Resources>
<ResourceDictionary>
<DataTemplate x:Key="validPersonTemplate">
<ViewCell>
...
</ViewCell>
</DataTemplate>
<DataTemplate x:Key="invalidPersonTemplate">
<ViewCell>
...
</ViewCell>
</DataTemplate>
<local:PersonDataTemplateSelector x:Key="personDataTemplateSelector"
ValidTemplate="{StaticResource validPersonTemplate}"
InvalidTemplate="{StaticResource invalidPersonTemplate}" />
</ResourceDictionary>
</ContentPage.Resources>
...
</ContentPage>
2.use like this:
<ListView x:Name="listView" ItemTemplate="{StaticResource personDataTemplateSelector}"
/>
For more details, you can check:
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/templates/data-templates/selector
Besides, you can also try ListView Grouping, for more details:
https://learn.microsoft.com/en-ie/xamarin/xamarin-forms/user-interface/listview/
https://learn.microsoft.com/en-us/samples/xamarin/xamarin-forms-samples/userinterface-listview-grouping/
the first ListView Occupies the entire remaining height
For me it looks like its the issue with footer which is taking extra space inside listview. Can you just put the Empty listview footer and see if it works:
<ListView.Footer>
<Label />
</ListView.Header>
I have an ImageButton which will work fine with some properties, but as soon as i add these properties to it CornerRadius , BorderColor and BorderWidth it acts weird and it scales and also goes in a weird spot of the page.
here is the full xaml code:
<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"
mc:Ignorable="d"
x:Class="Accounting.MainPage">
<StackLayout Margin="3">
<Entry
x:Name="NameEntry"
Placeholder="Enter the Fullname"
/>
<Grid Margin="3,-6,3,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button
Margin="0,0,2,0"
VerticalOptions="Center"
x:Name="AddButton"
Text="Add"
HeightRequest="50"
BackgroundColor="#03A9F4"
TextColor="White"
CornerRadius="10"
Grid.Column="0"
Clicked="AddButton_Clicked"
/>
<ImageButton
Source="add.png"
Grid.Column="1"
HorizontalOptions="Center"
VerticalOptions="Center"
WidthRequest="50"
HeightRequest="50"
CornerRadius="50"
/>
<Button
Margin="2,0,0,0"
VerticalOptions="Center"
x:Name="DeleteButton"
Text="Delete"
HeightRequest="50"
BackgroundColor="#f44336"
TextColor="White"
CornerRadius="10"
Grid.Column="2"
Clicked="DeleteButton_Clicked"
/>
</Grid>
<ListView x:Name="WorkersListView" BackgroundColor="#ECEFF1" Margin="2" ItemSelected="WorkersListView_ItemSelected">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell TextColor="Black" Text="{Binding WorkerName}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
NOTE :
The behaviors i said is for the Image that i used in the ImageButton source not the button itself , see the Picture below, and I SHOULD ALSO SAY THAT THIS PROBLEM ONLY SHOWS ON XAMARIN FORMS PREVIEWER :
Can anyone tell me the problem with it and how to fix it?
Thanks for your help in advance.
Yes, it is just the case for Xamarin Previewer, it often has problems. And we apologize for the inconvenience.
The xamarin development team is doing their best to address this issue and we are urging them to release the latest version as soon as possible.
Of course, you can also try other alternate tools ,e.g. LiveXAMLand Xamarin live reload.
For more details, you can check:
https://www.livexaml.com/
https://marketplace.visualstudio.com/items?itemName=Xamarin.XamarinLiveReload
I have been trying all the "Qs that may have your answer" 3 days later, still no joy.
I have a XAML Page that holds a ListView of products and their details, using binding to a model called RackProducts as you can see:
<?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="PapillonWine.PapillonRackCatalogPage"
xmlns:local="clr-namespace:PapillonWine;assembly=PapillonWine"
xmlns:artina="clr-namespace:UXDivers.Artina.Shared;assembly=UXDivers.Artina.Shared"
xmlns:customContentView="clr-namespace:PapillonWine.NavBars"
Title="{ artina:Translate PageTitleProductsCatalog }"
BackgroundColor="{ DynamicResource MainWrapperBackgroundColor }"
x:Name="CatalogItemPage">
<ContentPage.Content>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="70" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<customContentView:CustomNavigationBar Grid.Row="0" x:Name="NavigationBarView" BackgroundColor="Transparent"/>
<ListView
x:Name="PapillonRackItems"
Grid.Row="1"
ItemsSource="{ Binding RackProducts }"
HasUnevenRows="True"
ItemSelected="OnItemSelected">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<local:PapillonCatalogItemTemplate />
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</ContentPage.Content>
</ContentPage>
Each product is displayed using the PapillonCatalogItemTemplate which holds four buttons (to view a carousel of product images, to add to cart, to view dimensions and lastly to share the product). This PapillonCatalogItemTemplate is as follows:
<?xml version="1.0" encoding="utf-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="PapillonWine.PapillonCatalogItemTemplate"
xmlns:local="clr-namespace:PapillonWine;assembly=PapillonWine"
xmlns:artina="clr-namespace:UXDivers.Artina.Shared;assembly=UXDivers.Artina.Shared"
xmlns:customContentView="clr-namespace:PapillonWine.NavBars"
xmlns:ffimageloading="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms"
xmlns:fftransformations="clr-namespace:FFImageLoading.Transformations;assembly=FFImageLoading.Transformations"
Padding="10" BackgroundColor="{ DynamicResource MainWrapperBackgroundColor }"
x:Name="CatalogItemTemplate">
<!-- FAVORITE ICON -->
<Grid>
<!-- COLUMN DEFS -->
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- ROW DEFS -->
<Grid.RowDefinitions>
<RowDefinition Height="0.45*" />
<RowDefinition><RowDefinition.Height><OnIdiom x:TypeArguments="GridLength" Phone="200" Tablet="400" /></RowDefinition.Height></RowDefinition>
</Grid.RowDefinitions>
<StackLayout Grid.Column="0" Grid.Row="0" Spacing="5" HorizontalOptions="FillAndExpand" WidthRequest="1000" >
<!-- PRODUCT NAME -->
<Label Text="{ Binding Name }" />
<!-- DESCRIPTION -->
<Label Text="{Binding Description}" />
<!-- BUTTONS -->
<StackLayout x:Name="buttonstack" Orientation="Horizontal" >
<!-- SHOW IMAGES -->
<artina:Button
x:Name="ImageCarousel"
Text="{ x:Static local:FontAwesomeWeb511Font.CameraRetro }"
Style="{StaticResource FontIcon}"
BindingContext="{Binding Source={x:Reference CatalogItemTemplate}, Path=BindingContext}"
Command="{Binding OnClickViewImageCarousel}"
CommandParameter="{Binding Source={x:Reference buttonstack}, Path=BindingContext}" >
<!-- SHOW CART -->
<artina:Button
Text="{ x:Static local:FontAwesomeWeb511Font.cartplus }"
Style="{StaticResource FontIcon}"
Clicked="OnBuyItemSelected">
</artina:Button>
<!-- SHOW DIMENSIONS -->
<artina:Button
Text="{ x:Static local:FontAwesomeWeb511Font.RulerCombined }"
Style="{StaticResource FontIcon}"
Clicked="OnDimensionsSelected" >
<!-- SHOW IMAGES -->
<artina:Button
Text="{ x:Static local:FontAwesomeFont.Share }"
Style="{StaticResource FontIcon}"
Clicked="OnShareSelected" >
</StackLayout>
</StackLayout>
<ffimageloading:CachedImage
Grid.Column="0" Grid.Row="1"
Source="{ Binding Image }" />
</Grid>
</ContentView>
If I click the ffloading image at the bottom of the template item, the OnItemSelected button fires, and I get a nice new view page with a picture of the product that I selected and all its item details... bully! The code it fires is as follows:
public async void OnItemSelected(object sender, SelectedItemChangedEventArgs e)
{
var selectedItem = ((ListView)sender).SelectedItem;
var page = new PapillonRackItemViewPage(((RackProduct)selectedItem).Id);
await Navigation.PushModalAsync(page);
}
However... if I try to fire one of the buttons within the item template (for example the one directly beneath "SHOW IMAGES", nothing happens. I have left the Commmand, CommandParameter and Binding arguments in that first button but I'm not sure they're correct. I have tried ICommand route, TapGestureRecognizer route, and tried most similar posts, and I really need help on this one. How do I pass the same binding context as in the ListView and its "RackProducts" binding, through button items within a list view? Any chance of a much needed helping hand? Thanks!
in your XAML
Clicked="OnClickViewImageCarousel" CommandParameter="{Binding .}"
then in the code behind
protected void OnClickViewImageCarousel(object sender, EventArgs e)
{
var selectedItem = (RackProduct)((Button)sender).CommandParameter;
}
I'm trying to create a view that has several controls centered inside a StackLayout. When I have just one like this:
<StackLayout Orientation="Vertical" HorizontalOptions="Center" >
<controls:BindablePicker />
</StackLayout>
It works fine:
Centered
However, when I try to add a ListView, e.g.:
<StackLayout Orientation="Vertical" HorizontalOptions="Center" >
<controls:BindablePicker />
<ListView HorizontalOptions="Center" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout Orientation="Horizontal">
<controls:BindablePicker Title="Length" />
<controls:BindablePicker Title="Units" />
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
Everything is left justified and takes up the entire screen:
Left justified
I'd like the widths of all controls to be as short as possible centered on the screen. Right now I'm using a ListView because I'm binding a list of objects and I thought that would be easier than trying to use a Grid.
Any suggestions would be greatly appreciated. Thanks.
UPDATE I updated my ViewCell to replace the StackLayout with a Grid, then put the ListView inside a grid as follows:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ListView Grid.Row="0" Grid.Column="1" HorizontalOptions="Center" SeparatorVisibility="None">
This is pretty much what I want, except the top picker is taking up the entire width of the screen, instead of being only as wide as it needs to be and centered.
There is one small difference between your first StackLayout example and the second StackLayout example (the example inside of the ViewCell), and this is causing the trouble you're experiencing:
The first StackLayout example is Orientation="Vertical"
The second StackLayout example (the example inside of your ViewCell) is Orientation="Horizontal"
StackLayouts in Xamarin.Forms only honor the HorizontalOptions property when Orientation="Vertical", and only honor the VerticalOptions property when Orientation="Horizontal".
This "feature" of StackLayouts is not well documented, and I couldn't find an example link that specifies it. Personally, I learned this fact from an instructor during a Xamarin University class.
To center the controls of the ViewCell, use a Grid layout instead of a StackLayout. Here's An example:
http://www.trsneed.com/customize-xamarin-forms-listview-with-viewcell/