How can I add a icon(fontAwesome) to my toolbar item? Referring to this link, I managed to set a fontawesome to my label. But how do I do that for toolbar itrm?
My code:
ToolbarItem Save = new ToolbarItem();
Save.Text = FontAwesome.FAFloppyO;
Save.Order = ToolbarItemOrder.Primary;
I also tried adding icon attribute to my toolbarItem but doesn't work.
I have managed to achieve this out-of-box using Iconize library for Xamarin Forms. It is quite easy to set up.
Now, to save you extra hours of frustrations, you need to:
Use IconNavigationPage as parent instead of NavigationPage.
Use IconToolbarItem instead of ToolbarItem.
The Icon property should be set, not the Text property (i.e. Icon="fa-user")
Let me know if this solves your issue.
You can use NavigationPage.TitleView instead of Toolbar or Toolbar item.
All you have to do is just adding fontawesome libraries to each platform and than set font familiy property according of target platform.
<NavigationPage.TitleView>
<StackLayout Orientation="Horizontal">
<Button HorizontalOptions="EndAndExpand" Text="">
<Button.FontFamily>
<OnPlatform x:TypeArguments="x:String">
<On Platform="iOS" Value="Font Awesome 5 Free" />
<On Platform="Android" Value="fa-solid-900.ttf#fa-solid" />
</OnPlatform>
</Button.FontFamily>
</Button>
</StackLayout>
this is the one of the basic usage. For better usage you can create your own static resources and apply to button or what ever other items.
This is a code sample from one of my project:
<!-- Toolbar -->
<NavigationPage.TitleView>
<Grid HeightRequest="50" BackgroundColor="{StaticResource DarkBackgroundColor}" Margin="0" Padding="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
</Grid.ColumnDefinitions>
<!-- Title -->
<Label Text="Inventory" Style="{StaticResource TitleViewTitleLabel}"/>
<Button Grid.Column="1" Text=""
Style="{StaticResource FontAwesomeButtonRegularTitleViewButton}"
Command="{Binding SyncDataCommand}"/>
<Button Grid.Column="2" Text=""
Style="{StaticResource FontAwesomeButtonRegularTitleViewButton}"
Command="{Binding ShowFunctionalityCommand}"/>
<Button Grid.Column="3" Text=""
Style="{StaticResource FontAwesomeButtonRegularTitleViewButton}"
Command="{Binding AddNewInventoryCommand}"/>
</Grid>
</NavigationPage.TitleView>
Related
I've got a button using a font icon from Material Design Icons. (Displaying this icon as well as several others is working fine so converter omitted for brevity). Here is the XAML for the button:
<Button Margin="10"
Padding="0"
BackgroundColor="{StaticResource Background}"
CornerRadius="25"
FontFamily="{StaticResource MaterialFontFamily}"
FontSize="36"
HeightRequest="50"
HorizontalOptions="EndAndExpand"
Text="{Binding PlusIcon, Converter={StaticResource NameToIcon}}"
WidthRequest="50" />
As you can see I've got the padding set to 0, but it still displays like this:
Just to test I have done this with regular text too:
Looks fine if I set the font size smaller, but this is not what I want:
How do I force removal of the padding? And why is the text not centered when I change the font size? Issue happens on IOS and Android.
You should use the ImageButton with a FontImageSource
First you declare you FontImageSource in your styles:
<FontImageSource x:Key="IconBikeSmall"
FontFamily="{StaticResource FontAwesome}"
Glyph="{x:Static styles:IconFont.Biking}"
Size="{StaticResource SizeSmallIcon}"
Color="{StaticResource SecondaryColor}" />
Then you simply use it as value for the Source property of your button:
<ImageButton Source="{StaticResource IconBikeSmall}"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
Or even use it directly like this:
<ImageButton HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" >
<ImageButton.Source>
<FontImageSource
FontFamily="{StaticResource FontAwesome}"
Glyph="{x:Static styles:IconFont.Biking}"
Size="{StaticResource SizeSmallIcon}"
Color="{StaticResource SecondaryColor}" />
</ImageButton.Source>
</ImageButton>
My problem is with the viewcell, the OnDelete command is not found due to it being of the IssueModel class, I've attempted to change the binding-context of the Listview, but that doesn't change anything except the above binding.
Is there any way to change the binding context of the viewcell so I don't have to put the command into to IssueModel?
freshMvvm:FreshBaseContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:converters="clr-namespace:ASFT.Converters;assembly=ASFT"
xmlns:freshMvvm="clr-namespace:FreshMvvm;assembly=FreshMvvm"
xmlns:helperMethods="clr-namespace:ASFT.HelperMethods;assembly=ASFT"
x:Class="ASFT.Pages.IssueListPage">
<ContentPage.Resources>
<ResourceDictionary>
<converters:SelectedItemEventArgsToSelectedItemConverter x:Key="SelectedItemConverter" />
<converters:DateTextConverter x:Key="DateToTextConverter" />
</ResourceDictionary>
</ContentPage.Resources>
<ListView ItemsSource="{Binding Issues}" SeparatorColor="#444444" RowHeight="90" IsPullToRefreshEnabled="True" IsRefreshing="{Binding IsBusy}" RefreshCommand="{Binding PullRefreshCommand}" >
<ListView.Behaviors>
<helperMethods:EventToCommandBehavior EventName="ItemSelected"
Command="{Binding OnSelectedIssueCommand}"
Converter="{StaticResource SelectedItemConverter}" />
</ListView.Behaviors>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell >
<ViewCell.ContextActions>
<MenuItem Command="{Binding OnDelete}" Text="Delete" IsDestructive="True" />
</ViewCell.ContextActions>
<ViewCell.View>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Image Grid.Row="0" Grid.RowSpan="3" Grid.Column="0" Source="{Binding SeverityImagePath}" HorizontalOptions="Center" VerticalOptions="Center" HeightRequest="70"/>
<Image Grid.Row="0" Grid.RowSpan="3" Grid.Column="2" Source="{Binding StatusImagePath}" HorizontalOptions="Center" VerticalOptions="Center" HeightRequest="60"/>
<Label Grid.Row="0" Grid.Column="1" Text="{Binding Title}" LineBreakMode="TailTruncation" YAlign="Center" VerticalOptions="Start" Font="Bold, Medium"/>
<Label Grid.Row="1" Grid.Column="1" Text="{Binding Created, Converter={StaticResource DateToTextConverter}}" YAlign="Center" VerticalOptions="Start" Font="Medium"/>
<Label Grid.Row="2" Grid.Column="1" Text="{Binding Description}" LineBreakMode="WordWrap" YAlign="Start" VerticalOptions="Start" Font="Small"/>
</Grid>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</freshMvvm:FreshBaseContentPage>
Edit:
I've attempted one of the answers but that didn't work. This just gets an error message: expected type is object, but type is IssueListPageModel
xmlns:pageModels="clr-namespace:ASFT.PageModels;assembly=ASFT"
<MenuItem Command="{Binding Path=BindingContext.OnDelete, Source={pageModels:IssueListPageModel}}" Text="Delete" IsDestructive="True" />
Add a x:Name attribute to your freshMvvm:FreshBaseContentPage, like i.e.: x:Name="MyAwesomePage".
Now change your ViewCell binding like this:
<MenuItem Command="{Binding Path=BindingContext.OnDelete, Source={x:Reference Name=MyAwesomePage}}" Text="Delete" IsDestructive="True" />
Now the binding source is set to the page by using its name. And the path is set to the property BindingContext.OnDelete. So, in your backing view model for this page there should be a OnDelete property.
To clarify the separate components like you've asked in the comments.
The Path= is omitted with a regular binding. When not explicitly mentioned, {Binding MyProperty} means the same as '{Binding Path=MyProperty}'. Path means the path to the value that needs to be bound from the BindingContext, so effectively the property that you are binding to.
The Source is used to specify what is the source of the Path. Which is in itself another binding. In our case to a reference which is known by the name we just gave the page. This way, the binding of the ViewCell knows to start at the Source and then search for the Path to retrieve its value. I hope this makes it a bit clear.
You can reference anything here if you want to, as long as you have access to the instance of the class here. I would, however, recommend to keep it to the BindingContext which is effectively the view model (note: BindingContext is the actual property of your page that contains the view model). Else you will lose overview very quickly.
I have a ListView with two columns, the leftmost of which contains an <Image> like this:
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*" />
<ColumnDefinition Width="0.5*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
</Grid.RowDefinitions>
<AbsoluteLayout Grid.Column="0" Grid.Row="0">
<Image
HeightRequest="130"
Aspect="AspectFill"
Source="{Binding DynamicOfferImage}"
local:ImageBinding.URL="{Binding DynamicOfferURL}"
AbsoluteLayout.LayoutBounds="1,1,1,1"
AbsoluteLayout.LayoutFlags="All">
<Image.Aspect>
<OnPlatform x:TypeArguments="Aspect">
<On Platform="iOS">AspectFit</On>
<On Platform="Android">AspectFit</On>
</OnPlatform>
</Image.Aspect>
<Image.GestureRecognizers>
<TapGestureRecognizer
Tapped="OnImageTapGestureRecognized"
NumberOfTapsRequired="1" />
</Image.GestureRecognizers>
</Image>
<StackLayout IsVisible="{Binding IsRedeemed}" Margin="20" AbsoluteLayout.LayoutBounds="1,1,1,1" AbsoluteLayout.LayoutFlags="All">
<ContentView Padding="3" BackgroundColor="#d9534f">
<Label Text="{loc:_ S=LoginIsRedeemed}" FontSize="Medium" TextColor="#ffffff" HorizontalOptions="Center"></Label>
</ContentView>
</StackLayout>
</AbsoluteLayout>
<StackLayout Grid.Column="1" Grid.Row="0">
<!-- Text here, irrelevant to question -->
</StackLayout>
</Grid>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
The <Image>'s Source property is bound to a URL of a JPEG image hosted on Amazon S3. The problem is most of the time these images are downloaded fine, however sometimes one image, or even all images, won't download (or won't display?)
This issue doesn't go away until the user re-installs the app. Even restarting the app doesn't count, it has to be an actual re-installation.
Below is a mockup of what this ends up looking like in some scenarios:
Any help much appreciated!
NOTE: This is not a duplicate of Xamarin Forms ListView Images Sometimes Displays, Sometimes Doesn't (UWP), as that scenario described is different.
I ended up taking G.hakim's advice and decided to employ FFImageLoading (via NuGet package) for the images. It was pretty simple although I had to use a slightly older version for Xamarin.Android. Some weird linker error occurs with the latest version (2.4.4.859) and had to go back to 2.4.1. Either way it works really well and even adds a little animation to the images on Xamarin.iOS.
Here was my code before:
<Image
HeightRequest="130"
Aspect="AspectFill"
Source="{Binding ImageURL}"
local:ImageBinding.URL="{Binding LinkURL}"
AbsoluteLayout.LayoutBounds="1,1,1,1"
AbsoluteLayout.LayoutFlags="All">
<Image.Aspect>
<OnPlatform x:TypeArguments="Aspect">
<On Platform="iOS">AspectFit</On>
<On Platform="Android">AspectFit</On>
</OnPlatform>
</Image.Aspect>
<Image.GestureRecognizers>
<TapGestureRecognizer
Tapped="OnImageTapGestureRecognized"
NumberOfTapsRequired="1" />
</Image.GestureRecognizers>
</Image>
In order to get FFImageLoading to work you have to add this to the root <ContentPage> element:
xmlns:ffimageloading="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms"
xmlns:fftransformations="clr-namespace:FFImageLoading.Transformations;assembly=FFImageLoading.Transformations"
Then I was able to do this:
<ffimageloading:CachedImage
AbsoluteLayout.LayoutBounds="1,1,1,1"
AbsoluteLayout.LayoutFlags="All"
HeightRequest="130"
DownsampleToViewSize="true"
Source="{Binding ImageURL}"
local:ViewBinding.URL="{Binding LinkURL}">
<ffimageloading:CachedImage.GestureRecognizers>
<TapGestureRecognizer
Tapped="OnViewTapGestureRecognized"
NumberOfTapsRequired="1" />
</ffimageloading:CachedImage.GestureRecognizers>
</ffimageloading:CachedImage>
In order for it to work with my TapGestureRecognizer I changed the ((Image)sender) cast in the method to a ((View)sender) cast because the CachedImage class in FFImageLoading doesn't actually inherit from Image, it inherits from View. Something to keep in mind if you have gestures or even custom bindings.
Aside from that it is very plug-and-play and I'm very happy with the outcome.
Im trying to do a screen with 6 buttons on it,and i need for every screen to be the same size,because right now some smaller or bigger screens the buttons are getting chopped or getting too small.
<StackLayout>
<StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand">
<StackLayout Orientation="Vertical" HorizontalOptions="FillAndExpand">
<Button Text="Linfócito" Font="{StaticResource Fonte}" ContentLayout="top,0" FontAttributes="{StaticResource Atributo}" WidthRequest="150" HeightRequest="200" Image="Linfocito.jpg"/>
<Button Text="Linfocito" Font="{StaticResource Fonte}" WidthRequest="150" ContentLayout="top,0" FontAttributes="{StaticResource Atributo}" HeightRequest="200" Image="Linfocito.jpg" Clicked="Button_Clicked"/>
<Button Text="Linfocito22" Font="{StaticResource Fonte}" WidthRequest="150" ContentLayout="top,0" FontAttributes="{StaticResource Atributo}" HeightRequest="200" Image="" />
</StackLayout>
im doing in xaml using Xamarin.Forms,thanks in advance
you should be more specific on the desired layout but I presume that you want your buttons always fill the screen horizontally, independently of the screen resolution / size / density...
The problem
In your exemple you are using fixed sizes for your buttons using the 'WidthRequest' & 'HeightRequest' properties:
<Button ... WidthRequest="150" HeightRequest="200"... />
So in this case, it's normal that your buttons are cropped if the resolution is too small, or don't fill the screen if the resolution is high. Your buttons don't follow the screen resolution but the size you give them.
What you should do:
Use relative layouts. That means, instead of setting fixed sizes uses layout controls that automatically respond to 'constraints' instead of sizes.
In your case, I suggest you to use a Grid controls. Here is an example but there are many possible solutions:
<?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="GoodChapp.XForms.Views.MyPage">
<ContentPage.Content>
<!-- full screen grid -->
<Grid>
<!-- Define the rows containing your page controls -->
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="200" /> <!-- row that will contains buttons -->
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- Row 0: Put whatever you want inside -->
<!-- Height will stretch to its content -->
<!-- Row 1: This grid layouts your buttons horizontally -->
<!-- It will fill horizontally the whole screen -->
<!-- With 3 columns of the same size -->
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- button 1 -->
<Button Grid.Column="0"
Text="Linfócito"
Font="{StaticResource Fonte}"
FontAttributes="{StaticResource Atributo}"
Image="Linfocito.jpg"
/>
<!-- button 2 -->
<Button Grid.Column="1"
Text="Linfócito2"
Font="{StaticResource Fonte}"
FontAttributes="{StaticResource Atributo}"
Image="Linfocito.jpg"
/>
<!-- button 3 -->
<Button Grid.Column="2"
Text="Linfócito3"
Font="{StaticResource Fonte}"
FontAttributes="{StaticResource Atributo}"
Image="Linfocito.jpg"
/>
</Grid>
<!-- Row 2: The last row will take the remaining available height -->
</Grid>
</ContentPage.Content>
Key points are the definition of page's layout and defining correct grid rows heights & column widths...
There is a good presentation of the Grid control here Xamarin Fors Grid Control but I suggest you to read the whole "Layout" paragraph. You will have a clear idea of the different solutions for your problem.
But to summarize, in my applications, and I think it's a good design practice, I try to use the less possible fixed widths and heights.
Tell me if it's clear enough. Else don't forget to validate the answer. Thanks
I am searching for a good example how to build a master/detail view for UWP Win 10 app like shown on this page: https://msdn.microsoft.com/en-us/library/windows/apps/dn997765.aspx
For example Windows Mail app has the same master/detail view. How can I implement this style? On the left side I think to use a listview, but how to show the data in the Detail side? Can I use a Frame or ContentPresenter? How can enable/disable the detail view on phone/tablet/pc?
Hope there is example or tutorial which shows how to deal with this.
It's good to have some app architecture... The Windows XAML community already worked on it.
https://github.com/Windows-XAML/Template10/tree/master/Samples/MasterDetail
I think:
https://blogs.msdn.microsoft.com/johnshews_blog/2015/09/09/a-minimal-mvvm-uwp-app/
is a good exemple.
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Vertical">
<ListView x:Name="MainList"
ItemsSource="{x:Bind Organization.People, Mode=OneWay}"
SelectedIndex="{x:Bind Organization.SelectedIndex, Mode=TwoWay}"
MinWidth="250" Margin="5">
<ListView.ItemTemplate>
<DataTemplate x:DataType="viewModels:PersonViewModel" >
<TextBlock Text="{x:Bind Name, Mode=OneWay}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
<StackPanel Grid.Column="2" Orientation="Vertical">
<TextBox
Text="{x:Bind Organization.SelectedPerson.Name, Mode=TwoWay, FallbackValue=''}"
Margin="5" />
<TextBox
Text="{x:Bind Organization.SelectedPerson.Age, Mode=TwoWay, FallbackValue='0'}"
Margin="5" />
</StackPanel>
</Grid>
You can also find another exemple in samples app :https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/XamlListView
You can also use the MasterDetailsView Control provided by the UWP Community Toolkit.
You can use region frames. Here is an example for MvvmCross.
<SplitView x:Name="RootSplitView"
DisplayMode="Inline"
OpenPaneLength="256"
IsTabStop="False">
<SplitView.Pane>
<StackPanel Margin="0,50,0,0">
<Button Content="Second" Command="{x:Bind Vm.SecondCommand}" />
<Button Content="Third" Command="{x:Bind Vm.ThirdCommand}" />
</StackPanel>
</SplitView.Pane>
<!-- OnNavigatingToPage we synchronize the selected item in the nav menu with the current page.
OnNavigatedToPage we move keyboard focus to the first item on the page after it's loaded and update the Back button. -->
<Frame x:Name="FrameContent">
<Frame.ContentTransitions>
<TransitionCollection>
<NavigationThemeTransition>
<NavigationThemeTransition.DefaultNavigationTransitionInfo>
<EntranceNavigationTransitionInfo/>
</NavigationThemeTransition.DefaultNavigationTransitionInfo>
</NavigationThemeTransition>
</TransitionCollection>
</Frame.ContentTransitions>
</Frame>
</SplitView>
In the code behind file add
public Frame AppFrame { get { return (Frame)this.WrappedFrame.UnderlyingControl; } }
Add this in setup.cs file
protected override IMvxWindowsViewPresenter CreateViewPresenter(IMvxWindowsFrame rootFrame)
{
return new MvxWindowsMultiRegionViewPresenter(rootFrame);
}
for newer versions use:
protected override IMvxWindowsViewPresenter CreateViewPresenter(IMvxWindowsFrame rootFrame)
{
return new MvxWindowsMultiRegionViewPresenter(rootFrame);
}
Add following attribute at the top of the code behind file of child view:
[MvxRegion("FrameContent")]
For later versions:
[MvxRegionPresentation("FrameContent")]
Use this for navigating to child view:
ShowViewModel<SecondViewModel>()
Refer to this link: https://depblog.weblogs.us/2015/11/23/mvvmcross-uwp-splitview/
Examples: https://github.com/MvvmCross/MvvmCross-Samples/tree/master/XPlatformMenus