Xamarin Forms: How to access button name in XAML from C#? - c#

I have the following XAML markup:
<ListView x:Name="wordsListView">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout>
<Label Text="{Binding Keyword}" />
<Button Text="Click Me" x:Name="randomButton"></Button>
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
And in my .xaml.cs file I have the button clicked event for the random button defined as below:
randomButton.Clicked += (object sender, EventArgs e) =>
{
a = rand.Next(words.Count);
word = words[a];
};
But somehow when I build my project I kept getting an error: The name randomButton does not exists in the current context. Can anyone tell me what I'm doing wrong and how it should be done?

You can't access any control by name or even give it a name as long as it is on template view , naming it is not appropriate as long as this control on template will be repeated on run time!
but you can access the whole control from the Sender of the click event ... and this depends on your development approach

Hope it will help others.
There is nothing wrong with your code.You can try these 2 ways:
First, save xaml file and use this.randomButton. Try if it works.
Else Clean the solution and try again. If that didn't work, restart the Visual Studio.

Related

XAML Page Formatting Issue

Im trying to be methodical in my aproach to this school project but I am having XAML difficulties. So far I have been able to get my main page to look exactly how I want it to except for not being able to print any data using a list.view with a basic test string.
Heres the entire page cs file: https://gist.github.com/GermanHoyos/2ffed121e9d9b7026e0b1c6f36c2ce9a
Heres an image of the code in question(specificaly line 85):
Souldnt line 85 appear inside of the List.view as "test".
The reason im trying to get the string "test" to appear in the bottom most box is because eventually I would like to populate an entire list of data in this bottom most section. But I cant begin to even try things like {binding var} if I cant get a basic string to apear first.
Any help would be appreciated!
Heres list code:
<ListView x:Name = "fullViewOfTermsCourses"
BackgroundColor="PowderBlue"
HeightRequest="1"
>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell IsEnabled="True">
<StackLayout Orientation="Horizontal" HorizontalOptions="CenterAndExpand">
<Label Text="test" VerticalOptions="CenterAndExpand" TextColor="Blue"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

Display popup on item hold in listview for x seconds?

I have a listview with different items inside it. They are stored in a database and a list etc.. On item hold for like 2 sec, i want a display popup to appear saying, "are you sure you want to delete this item" or something like that.
I currently only have this pop up to appear on "ItemSelected". How can i make so that if i hold down on an item for 2 sec, the display alert appear?
Current code so far
private async void ExampleListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
var result = await DisplayAlert("Delete", "Are you sure you want to delete this object?", "Delete", "Cancel");
}
I Found this great nuget package site. Amazing and worked for me really well!
http://www.mrgestures.com/
There is event as tapped, LongPressed, LongPressing etc. Use LongPressing event in this case.
Found this Here
<ListView x:Name="ContextDemoList" ItemSource="{Binding ListOfItems}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.ContextActions>
<MenuItem Clicked="OnDelete" CommandParameter="{Binding .}"
Text="Delete" IsDestructive="True" />
</ViewCell.ContextActions>
<StackLayout Padding="15,0">
<Label Text="Delete Me" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
And the CodeBehind to handle the events:
public void OnDelete (object sender, EventArgs e) {
var mi = ((MenuItem)sender);
var selectedItem = mi.CommandParameter; // May need to cast this object
vm.ListOfItems.Remove(selectedItem);
}
Where ListOfItems is your ObeservableCollection.

Getting current item by clicking button within a ListView (Xamarin.Forms)

I have following list view (the item source is set outside and a list of strings):
<?xml version="1.0" encoding="utf-8" ?>
<ListView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XXX.EditItemsList">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<Label Text="{Binding .}"/>
<Button Text="Delete"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
With clicking the button, I want to delete the current item (string) in the list. How is this possible?
Thanks for your help :)
In principle i think the answer given by #Krzysztof Skowronek is right, I will simply try to elaborate on it, and avoid the use of ViewModel since it seems you are not using it (although the use of it is a Best Practice on Xamarin Forms).
Following your own code, i wrote the following code in XAML:
<?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="clr-namespace:DeleteButton"
x:Class="DeleteButton.MainPage">
<ListView x:Name="listView"
HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<Label Text="{Binding .}"/>
<Button Text="Delete" Clicked="Delete"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
About this part of the solution i would give the following comments:
Note the use of ConntentPage instead of ListView at the top of the XAML, is that intentional?
Then, note the addition of x:Name on ListView. It will be used to communicate with the ListView from the code behind.
Additionally notice the use of HasUnevenRows set to True. This causes the ListView to adjust automatically the height of the rows.
Finally see that in Button i have set the event Clicked to "Delete", which is the name of the event handler in the code behind as you will see.
On the code behind i wrote:
using System;
using System.Collections.ObjectModel;
using Xamarin.Forms;
namespace DeleteButton
{
public partial class MainPage : ContentPage
{
ObservableCollection<String> list;
public MainPage()
{
InitializeComponent();
}
protected override void OnAppearing()
{
base.OnAppearing();
list = new ObservableCollection<string>()
{
"Task 1", "Task 2", "Task 3", "Task 4", "Task 5",
"Task 6", "Task 7", "Task 8", "Task 9", "Task 10"
};
listView.ItemsSource = list;
}
public void Delete(Object Sender, EventArgs args)
{
Button button = (Button)Sender;
StackLayout listViewItem = (StackLayout)button.Parent;
Label label = (Label)listViewItem.Children[0];
String text = label.Text;
list.Remove(text);
}
}
}
There i define the list of strings as an ObservableCollection (ObservableCollection causes the ListView to get a notification each time it changes, so that the ListView updates its contents, see the docu for more details).
Then i set the ItemSource property of the ListView to the collection of Strings, as you have already done.
Finally comes the EventHandler Delete, called by the Click event on Button, in XAML. The algorithm here is quite simple:
First the sender is cast to a Button (we know that the object firing the event is a Button).
Then we walk up the hierarchy tree up to the StackLayout containing the Button and the Label and retrieve the first child of it, which we know is the Label.
Once we have the Label we retrieve its Text property and call the Remove method of the collection to get ride of that item.
And that's it.
Note: If i would implement this functionality myself i would rather define a collection of objects which would containt a Text property as well as an Id property in order to remove exactly the element tapped. In the code above, if the collection contains two identical strings, the EventHandler would go simply for the first occurrence.
I hope this helps you to find the right way to solve your problem.
If you don't want to use Commands, you can use the Button's Clicked event. IE,
<Button Text="Delete" Clicked="HandleDeleteButtonClicked" />
Then in your code behind file,
private void HandleDeleteButtonClicked(object sender, EventArgs e)
{
// Assuming your list ItemsSource is a list of strings
// (If its a list of some other type of object, just change the type in the (cast)):
var stringInThisCell = (string)((Button)sender).BindingContext;
// Now you can delete stringInThisCell from your list.
myList.Remove(stringInThisCell);
}
If we are willing to keep MVVM approach, then in your View, name the ContentPage (or whichever root element is there) and use it as Source to bind command:
<?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="canaraydash.View.InviteListPage"
x:Name="InvitesView">
<ListView x:Class="XXX.EditItemsList">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<Label Text="{Binding .}" />
<Button Text="Delete"
Command="{Binding Path=BindingContext.AcceptRequestCommand, Source={x:Reference InvitesView}}"
CommandParameter="{Binding .}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
and in your ViewModel, define 'AcceptRequestCommand' command!
Create a DeleteItem command with a parameter in your control (or it's ViewModel preferably) and then in xaml:
<DataTemplate>
<ViewCell>
<StackLayout>
<Label Text="{Binding .}"/>
<Button Text="Delete" Command="{Binding Source={this should be your VM for the whole thing}, Path=DeleteItem}" CommandParameter="{Binding}"/>
</StackLayout>
</ViewCell>
</DataTemplate>
In command:
list.Remove(parameter);
If the the list is obeservable, it will disappear.
Here's my solution on the problem
<DataTemplate>
<Button Text="{Binding DisplayName}" Image="tab_about.png" ContentLayout="Top,0" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"
Command="{Binding Source={RelativeSource AncestorType={x:Type vm:AnimationViewModel}}, Path=AnimationCommand}"
CommandParameter="{Binding .}" />
</DataTemplate>
And the model view file is a normal command :
public ObservableCollection<LedAnimation> AnimationList { get; }
public Command<LedAnimation> AnimationCommand { get; }
public AnimationViewModel()
{
Title = "Animation";
AnimationList = new ObservableCollection<LedAnimation>();
AnimationCommand = new Command<LedAnimation>(OnLedAnimationTap);
_serverService.AnimationCapabilities.ForEach(x => AnimationList.Add(x));
}
private void OnLedAnimationTap(LedAnimation animation)
{
if (animation == null)
return;
Console.WriteLine($"VM:{animation.Name}");
}

Xamarin Forms Disable ListView Load Animation

<ListView x:Name="myList" ItemTapped="OnMyItemTapped" ItemsSource="{Binding myList}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout> CONTENT HERE </StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
where myList is an ObservableCollection
Desired: Displays all list items immediately at once without animation
Actual: Displays list items one at a time (similar to the add item animation)
Any ideas?
(This sequential displaying of items is significantly more noticeable when the list of items within the list view is larger)
The only way I've found to do it is to use a custom renderer.
These are the lines I'm using to disable the insert, delete and reload rows animations:
if (e.OldElement != null)
{
InsertRowsAnimation = UITableViewRowAnimation.None;
DeleteRowsAnimation = UITableViewRowAnimation.None;
ReloadRowsAnimation = UITableViewRowAnimation.None;
}
This needs to be placed in your CustomListViewRenderer that is inheriting from Xamarin forms ListViewRenderer.
I put mine in the OnElementChanged event.
You can use a platform specific property to disable animations:
<ContentPage ...
xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core">
<StackLayout Margin="20">
<ListView ios:ListView.RowAnimationsEnabled="false">
</ListView>
</StackLayout>
</ContentPage>
Read more here:
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/platform/ios/listview-row-animations

display the documentlibrary folders in windows 8 app

i'm getting the documentlibrary folders. but i don't know how to display the geeting folders in a MainPage.Xaml (design page).
here is my code:
var folders = await KnownFolders.DocumentsLibrary.GetFoldersAsync();
if anyone guide me. Thanks in advance.
Let's assume you've a ListView to show all the folders. And on click of a button, you want to show list of folders in DocumentsLibrary. For this, use following XAML:
<Button Content="Button" HorizontalAlignment="Left" Margin="216,172,0,0" VerticalAlignment="Top" Click="Button_Click_1"/>
<ListView x:Name="FolderList" HorizontalAlignment="Left" Height="100" Margin="216,328,0,0" VerticalAlignment="Top" Width="830">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding DisplayName}"></TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Now, in code behind write following code:
private async void Button_Click_1(object sender, RoutedEventArgs e)
{
var folders = await Windows.Storage.KnownFolders.DocumentsLibrary.GetFoldersAsync();
var data = folders.ToList<Windows.Storage.StorageFolder>();
FolderList.ItemsSource = data;
}
This will show you all the folders within the DocumentsLibrary in ListView.
Hope, it helps.
You need to use a ListView or GridView or ListBox in XAML (depending on what you want to do with it) and bind it to the folders list. Then you need an ItemTemplate to specify what you want displayed e.g. folder name, path, size etc

Categories

Resources