So I've run into a problem with Imagebuttons in XAML.
I usually render a background image from photoshop and then use this button everywhere and just add a label ontop that says what it does:
enter image description here
This here for isntance comes from this code (partially):
<!--Grid for button-->
<Grid Grid.Row="1" >
<ImageButton
x:Name="btn_register_mainpage"
Source="btn_emptydummy.png" BackgroundColor="#00000000"/>
<Label
FontFamily="arial"
TextColor="#272727"
Text="Profil erstellen"
HorizontalOptions="Center"
VerticalOptions="Center"/>
</Grid>
Now, this works just fine, unless you want to click on it.
As you can see I gave the button a name, I can now catch that name in code and delegate a click to it:
btn_register_mainpage.Clicked += async delegate
{
await Navigation.PushAsync(new Screen_EditInformation());
};
However, this only works when the user clicks on the button - but NOT on the label since this is on top and has no click assigned to it.
So, what I could do is just assign the same click event to both objects (the label and the image button) but that seems rather unusual.
What is the best way to have a custom image as a button with a label ontop that is clickable?
You can add GestureRecognizers to any control in Xamarin.Forms. In your case you could add one to the Grid layout
YourView.xaml
<Grid Grid.Row="1" >
<Grid.GestureRecognizers>
<TapGestureRecognizer
Tapped="OnTapGestureRecognizerTapped"
NumberOfTapsRequired="1" />
</Grid.GestureRecognizers>
<ImageButton
x:Name="btn_register_mainpage"
InputTransparent="True"
Source="btn_emptydummy.png" BackgroundColor="#00000000"/>
<Label
FontFamily="arial"
TextColor="#272727"
Text="Profil erstellen"
HorizontalOptions="Center"
VerticalOptions="Center"/>
</Grid>
YourView.xaml.cs
private void OnTapGestureRecognizerTapped(object sender, EventArgs e)
{
Navigation.PushAsync(new Screen_EditInformation());
}
You could add a TapGestureRecognizer on the label .
<Grid Grid.Row="1" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<ImageButton
Clicked="Button_Clicked"
Grid.Row="0"
x:Name="btn_register_mainpage"
BackgroundColor="LightBlue"/>
<Label
Grid.Row="0"
FontFamily="arial"
TextColor="#272727"
Text="Profil erstellen"
HorizontalOptions="Center"
VerticalOptions="Center">
<Label.GestureRecognizers>
<TapGestureRecognizer
Tapped="Button_Clicked"
NumberOfTapsRequired="1" />
</Label.GestureRecognizers>
</Label>
</Grid>
Related
I have created a ControlTemplate in the app.xaml, defining the graphic part, only in the cs I would like to take some elements, to which I have given the name, to assign them the click event, but it signals me that they do not exist in the current context .
Someone who could kindly tell me how to please?
Someone, if possible, modify the source of the webview present in the main page, directly from app.xaml.cs
My code in the template is this:`
<Application.Resources>
<ResourceDictionary>
<ControlTemplate x:Key="HeaderFooterTemplate"><ContentPresenter />
<StackLayout>
<BoxView HorizontalOptions="FillAndExpand" BackgroundColor="#DDDDDD" HeightRequest="2" Margin="0" />
<ScrollView Orientation="Horizontal">
<Grid RowSpacing="0">
<StackLayout Background="#c9ced6" HeightRequest="120" MinimumHeightRequest="120" Orientation="Horizontal" Grid.Row="0" Spacing="2">
<Grid WidthRequest="100" MinimumHeightRequest="120" BackgroundColor="#373B53" Padding="10" x:Name="Dashboard">
<Image Source="homeArancione" x:Name="imgDashboard" HorizontalOptions="Center" VerticalOptions="Center" WidthRequest="30" HeightRequest="30" Grid.Row="0" />
<Label Text="DASHBOARD" TextColor="#c9ced6" FontAttributes="Bold" HorizontalOptions="Center" Grid.Row="1" />
</Grid></Grid>
And in the reference page I recall it like this:
ControlTemplate="{StaticResource HeaderFooterTemplate}"
Graphically it works, but in the cs is I can't modify the texts to the labels or assign click events to the elements because it tells me that they don't exist in the current context
If you want to change the text or trigger the click event of the label in ControlTemplate, you could use the GestureRecognizers. The x:Name could not be found in the ControlTemplate directly.
<ControlTemplate x:Key="HeaderFooterTemplate">
<!--<ContentPresenter />-->
<StackLayout>
<BoxView HorizontalOptions="FillAndExpand" BackgroundColor="#DDDDDD" HeightRequest="2" Margin="0" />
<ScrollView Orientation="Horizontal">
<Grid RowSpacing="0">
<StackLayout Background="#c9ced6" HeightRequest="120" MinimumHeightRequest="120" Orientation="Horizontal" Grid.Row="0" Spacing="2">
<Grid WidthRequest="100" MinimumHeightRequest="120" BackgroundColor="#373B53" Padding="10" x:Name="Dashboard">
<Image Source="homeArancione" x:Name="imgDashboard" HorizontalOptions="Center" VerticalOptions="Center" WidthRequest="30" HeightRequest="30" Grid.Row="0" />
<Label Text="DASHBOARD" TextColor="#c9ced6" FontAttributes="Bold" HorizontalOptions="Center" Grid.Row="1">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"></TapGestureRecognizer>
</Label.GestureRecognizers>
</Label>
</Grid>
</StackLayout>
</Grid>
</ScrollView>
</StackLayout>
</ControlTemplate>
Code behind: App.xaml.cs
private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
{
Console.WriteLine("-----------");
var label = sender as Label;
label.Text = "Hello";
}
Update:
update the text of the label as soon as the page loads, without
having to click
Xamarin provide GetTemplateChild to get a named element from a template. The GetTemplateChild method should only be called after the OnApplyTemplate method has been called. If you want to call the OnApplyTemplate method, this template should be added for the contentpage.
You could refer to the thread i done before.
Xamarin SwipeView Open Left Item In ControlTemplate
I have a frame, the IsVisible is binded to a property in my model view that is set to false. when I change the flyout in my shell, the frame makes an appearance as the shell flyout is closing. Any idea why this is happening ?
// in my model view this is the property
public bool ShowPanel{ get { return _showPanel; } set { _showPanel =
value; OnPropertyChange(); } }
// in my view this is the panel
<Frame IsVisible="{Binding ShowPanel}" BackgroundColor="White" BorderColor="Purple" AbsoluteLayout.LayoutFlags="PositionProportional" WidthRequest="100" HeightRequest="200" AbsoluteLayout.LayoutBounds="0,0,200,250">
<local:ExtendedListView ItemTapped="ExtendedListView_ItemTapped" ItemsSource="{Binding AllItems}" IsVisible="{Binding ShowPanel}" SelectionMode="None" HorizontalScrollBarVisibility="Always" HorizontalOptions="Fill" VerticalOptions="Fill" BackgroundColor="Transparent">
<local:ExtendedListView.ItemTemplate >
<DataTemplate>
<ViewCell>
<Grid Padding="0">
<Grid.RowDefinitions>
<RowDefinition Height="20" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="20*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Image.Source="{Binding ImageUrl}" HorizontalOptions="FillAndExpand" VerticalOptions="CenterAndExpand" WidthRequest="50" HeightRequest="50" x:DataType="local1:ServiceLayers"></Image>
<CheckBox Grid.Column="1" IsChecked="{Binding IsVisible, Mode=TwoWay}" Color="Purple" VerticalOptions="Center" HorizontalOptions="Center" x:DataType="local1:ServiceLayers"></CheckBox>
<Label Padding="-5,0,0,0" HorizontalOptions="StartAndExpand" FontAttributes="Bold" TextColor="Black" Grid.Row="0" Grid.Column="2" HorizontalTextAlignment="Start" Text="{Binding Name}" x:DataType="local1:Service"></Label>
<Label></Label>
</Grid>
</ViewCell>
</DataTemplate>
</local:ExtendedListView.ItemTemplate>
</local:ExtendedListView>
</Frame>
// In the View Class
protected override bool OnBackButtonPressed() {
await Shell.Current.GoToAsync($"//{nameof(MainPage)}");
return true;
}
If the BindingContext is removed/changed as you navigate away from the page, the Frame would appear as the binding is invalidated and updated by the binding engine. You have two options:
Don't manually clear the BindingContext from the page as the navigation lifecycle and GC should clean up those resources on their own.
Use binding fallbacks to define behavior when the binding source can't be resolved (because you've nulled the BindingContext) or the binding source is resolved but the bound property is null.
I have this ListView:
<ListView x:Name="listview_items"
Margin="0,10,0,0"
VerticalScrollBarVisibility="Always"
HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="5"/>
</Grid.ColumnDefinitions>
<Label Text="{Binding itemText}"
FontSize="22"
Margin="0,5,0,5"
FontFamily="Font_11"
TextColor="#424242">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"/>
</Label.GestureRecognizers>
</Label>
<CheckBox
Color="#97A5AD"
IsChecked="{Binding isChecked}"
CheckedChanged="chk_accept_shipment_CheckedChanged"
Grid.Column="1"
Scale="1"
HorizontalOptions="End"
Margin="0,0,0,0"
x:Uid="{Binding itemID}"
x:Name="{Binding itemID}"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
As you can see, it contains a Label and a CheckBox, when the user checks the checkbox, I gets checked. But now, I have a gesture recognizer attached to the label. When the user taps the label, I want to find out which checkbox is next to the label and also check it (as if the user actually clicked the checkbox).
How do I find the corresponding checkbox to the label next to it?
I would personally bind the IsChecked property to my ViewModel.
Example:
<StackLayout
HorizontalOptions="Start"
Orientation="Horizontal">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Command="{Binding SelectAllCategoriesCommand}" NumberOfTapsRequired="1" />
</StackLayout.GestureRecognizers>
<CheckBox IsChecked="{Binding IsAllCategoriesSelected}" />
<Label Text="Select All Categories" />
</StackLayout>
The binded property can be something like :
private bool _isAllCategoriesSelected;
public bool IsAllCategoriesSelected
{
get => _isAllCategoriesSelected;
set
{
_isAllCategoriesSelected = value;
RaisePropertyChanged(() => IsAllCategoriesSelected);
}
}
First you have to pass CommandParameter in tap so you can get that in TapGestureRecognizer_Tapped In that you will get which Item table click so according that you have to check check box
<Label.GestureRecognizers>
<TapGestureRecognizer CommandParameter="{Binding itemID}" Tapped="TapGestureRecognizer_Tapped"/>
</Label.GestureRecognizers>
async void TapGestureRecognizer_Tapped(System.Object sender, System.EventArgs e)
{
var d = (TappedEventArgs)e;
var data = d.Parameter as int;//yor itemID type
}
I have List in xaml Page:
<ListView x:Name="ListTypeView" ItemsSource="{Binding ResourceType}" BackgroundColor="#FFFFFF" HeightRequest="210" WidthRequest="300" HorizontalOptions="CenterAndExpand" RowHeight="30">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout StyleId="Settings_StackLayout" Orientation="Horizontal" Padding="0" Margin="50,0,0,0">
<Label FontSize="Medium" HorizontalOptions="StartAndExpand" Text="{Binding ResourceType}" TextColor="Black" VerticalOptions="Center" WidthRequest="100"></Label>
<Image x:Name="Image" Source="{Binding Checkbox}" HorizontalOptions="StartAndExpand" WidthRequest="18" HeightRequest="18">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Source={x:Reference ListTypeView}, Path=BindingContext.ListTypeChangeCommand}" CommandParameter="{Binding .}"/>
</Image.GestureRecognizers>
</Image>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I want to disabling highlight on listView click
(remove list Selector which is blue in color default)
The way you do it if you define TapGestureRecognizer on image then if you tap an image your list item should not be selected anyway. If you want to disable selector on item tap then you need to use different event - list item tapped
lstItems.ItemTapped += LstItems_ItemTapped;
Then
private void LstItems_ItemTapped(object sender, ItemTappedEventArgs e)
{
//do whatever you need with selected item and reset it
((ListView)sender).SelectedItem = null;
}
I am trying to fill a Button with an Image. The button resides within a Grid. The problem is that the image is not fully filling the button. I have also tried to use the ImageButton control.
Here is how I am building my U.I:
<Grid Grid.Row="1" Grid.Column="1" x:Name="VotingGrid" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="45*" />
<ColumnDefinition Width="10*" />
<ColumnDefinition Width="45*" />
</Grid.ColumnDefinitions>
<Button Grid.Row="0" Grid.Column="0" Image="yay.png" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"/>
<Button Grid.Row="0" Grid.Column="2" Image="meh.png" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"/>
</Grid>
It currently looks like the image attached below, but I'd like to image to fill my button.
Any help will be appreciated!
Try to place an image instead of button.
You can make use of Tap Gesture Gesture Recognizer to take click events.
Try something like this :
<Image Source="tapped.jpg">
<Image.GestureRecognizers>
<TapGestureRecognizer
Tapped="OnTapGestureRecognizerTapped" />
</Image.GestureRecognizers>
</Image>
The code for the event handler
void OnTapGestureRecognizerTapped(object sender, EventArgs args) {
var imageSender = (Image)sender;
// Do something
DisplayAlert ("Alert", "Tap gesture recoganised", "OK");
}
Refer : Adding a Tap Gesture Gesture Recognizer
I have not used it myself but maybe you can use this one from XLab
https://github.com/XLabs/Xamarin-Forms-Labs/wiki/ImageButton