Hi guys I have a listview that I have made in Xamarin but not using Xamarin Forms. when I tap on a selected item it turns orange by default but I want to show a DisplayAlert when I tap on it. does anybody know how to solve this? below is my list view in C#
public string PhoneNumber;
StackLayout stackLayout = new StackLayout();
_listView = new ListView
{
ItemTemplate = new DataTemplate(() =>
{
Label nameLabel = new Label();
nameLabel.SetBinding(Label.TextProperty, "Name");
nameLabel.FontSize = 20;
Label addressLabel = new Label();
addressLabel.SetBinding(Label.TextProperty, "Address");
Label phoneLabel = new Label();
phoneLabel.SetBinding(Label.TextProperty, "Phone");
PhoneNumber = phoneLabel.Text;
return new ViewCell
{
View = new StackLayout
{
Padding = new Thickness(20, 5),
Orientation = StackOrientation.Horizontal,
Children =
{
new StackLayout
{
VerticalOptions = LayoutOptions.Center,
Spacing = 0,
Children =
{
nameLabel,
addressLabel,
phoneLabel,
}
}
}
}
};
})
};
_listView.HasUnevenRows = true;
_listView.ItemsSource = db.Table<Company>().OrderBy(x => x.Name).ToList();
stackLayout.Children.Add(_listView);
_listView.ItemTapped += _listView_ItemTapped;
Content = stackLayout;
}
private void _listView_ItemTapped(object sender, ItemTappedEventArgs e)
{
var phoneDialer = CrossMessaging.Current.PhoneDialer;
if (phoneDialer.CanMakePhoneCall)
phoneDialer.MakePhoneCall("11112222");
DisplayAlert("Phone Dial","Dialing" + e.Item.PhoneNumber, "Ok");
}
Just create ItemTapped method
_listView.ItemTapped += _listView_ItemTapped;
And implement it
private void _listView_ItemTapped(object sender, ItemTappedEventArgs e)
{
var item = e.Item as Company; //Company is your model class
DisplayAlert("Alert", item.Name, "Cancel");
}
Output screen
Related
I have an ObservableCollection with a list of users' data which is wrapped for multiselect page.
I added SearchBar to the multiselect page but I cannot make it work.
Code
public class WrappedItemSelectionTemplate : ViewCell
{
public WrappedItemSelectionTemplate() : base()
{
Label Title = new Label() { TextColor = Color.Black };
Title.SetBinding(Label.TextProperty, new Binding("Item.Title"));
Label Email = new Label() { FontSize = 14 };
Email.SetBinding(Label.TextProperty, new Binding("Item.Email"));
Switch mainSwitch = new Switch() { HorizontalOptions = LayoutOptions.End };
mainSwitch.SetBinding(Switch.IsToggledProperty, new Binding("IsSelected"));
StackLayout Stack = new StackLayout();
Stack.Children.Add(Title);
Stack.Children.Add(Email);
Grid grid = new Grid();
grid.Children.Add(Stack, 0,0);
grid.Children.Add(Email, 0, 1);
grid.Children.Add(mainSwitch, 1, 0);
View = grid;
}
}
public List<WrappedSelection<T>> WrappedItems = new List<WrappedSelection<T>>();
public SelectMultipleBasePage(List<T> items)
{
WrappedItems = items.Select(item => new WrappedSelection<T>() { Item = item, IsSelected = false }).ToList();
ListView mainList = new ListView()
{
ItemsSource = WrappedItems,
ItemTemplate = new DataTemplate(typeof(WrappedItemSelectionTemplate)),
};
mainList.ItemSelected += (sender, e) =>
{
if (e.SelectedItem == null) return;
var o = (WrappedSelection<T>)e.SelectedItem;
o.IsSelected = !o.IsSelected;
((ListView)sender).SelectedItem = null; //de-select
};
// SearchBar added
StackLayout Stack = new StackLayout();
SearchBar Search = new SearchBar();
Stack.Children.Add(Search);
Stack.Children.Add(mainList);
Search.TextChanged += (sender, e) =>
{
SearchBar_TextChanged();
};
Content = Stack;
void SearchBar_TextChanged()
{
//string keyword = Search.Text;
//mainList.ItemsSource =
}
}
When I used SearchBar in my cases before I was using new ObservableCollection for ItemsSource of my ListView, it was filtering it as I required.
But now am stuck and don't know how I can use the SearchBar for the field Title in that case with WrappedItems?
Although I prefer to see the code in Xaml and bound to VM with MVVM binding to make it easier to read . But I think I got what you need.
What you need to :
Search within WrappedItems and save the found result
Clear the ItemSource of the list view mainList.ItemSource.Clear();
Go through the foundItems and mainList.ItemSource.Add(foundItem);
If the Key is empty string "" then you go through original list and do the same work (i.e. clear the itemsource and add the whole data )
Actual screenshot of the problem
See the attached image here, I have 4 buttons in a gird when any of them are clicked they show me a webview, but for some reason I am unable to expand the web view so that it covers rest of the screen. As you can see in the picture , webview is in a single column and buttons are in 1 row. I would really appreciate help. Thanks.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace LocalDataAccess
{
public partial class RecipeSites : ContentPage
{
public RecipeSites()
{
this.Content = gridlayout();
}
public Grid gridlayout()
{
BackgroundColor = Color.White;
Button allrecipes = new Button
{
BackgroundColor = Color.Transparent,
};
allrecipes.Clicked += new EventHandler(allrecipes_Click);
allrecipes.Image = "alrecipe.png";
Button delia = new Button
{
BackgroundColor = Color.Transparent,
};
delia.Clicked += new EventHandler(delia_Click);
delia.Image = "delia.gif";
Button bbc = new Button
{
BackgroundColor = Color.Transparent,
};
bbc.Clicked += new EventHandler(bbc_Click);
bbc.Image = "bbc.jpg";
Button food = new Button
{
BackgroundColor = Color.Transparent,
};
food.Clicked += new EventHandler(food_Click);
food.Image = "food.jpg";
var grid = new Grid();
RowDefinition gridRow1 = new RowDefinition();
gridRow1.Height = new GridLength(7, GridUnitType.Star);
grid.RowDefinitions.Add(gridRow1);
grid.Children.Add(allrecipes, 0, 1);
grid.Children.Add(delia, 1, 1);
grid.Children.Add(bbc, 2, 1);
grid.Children.Add(food, 3, 1);
return grid;
}
public void food_Click(object sender, EventArgs e)
{
Grid sl = gridlayout();
WebView webView = new WebView
{
Source = new UrlWebViewSource
{
Url = " http://www.food.com/",
},
VerticalOptions = LayoutOptions.FillAndExpand,
};
var grid1 = new Grid()
{ VerticalOptions = LayoutOptions.FillAndExpand };
ColumnDefinition c2 = new ColumnDefinition();
c2.Width = new GridLength(10, GridUnitType.Star);
grid1.ColumnDefinitions.Add(c2);
grid1.Children.Add(webView, 3,1 );
this.Content = sl;
}
public void allrecipes_Click(object sender, EventArgs e)
{
Grid sl = gridlayout();
WebView webView = new WebView
{
Source = new UrlWebViewSource
{
Url = "http://allrecipes.co.uk/",
},
HorizontalOptions = LayoutOptions.FillAndExpand
};
sl.Children.Add(webView);
this.Content = sl;
}
public void delia_Click(object sender, EventArgs e)
{
Grid sl = gridlayout();
WebView webView = new WebView
{
Source = new UrlWebViewSource
{
Url = "http://www.deliaonline.com/recipes",
},
VerticalOptions = LayoutOptions.FillAndExpand
};
sl.Children.Add(webView);
this.Content = sl;
}
public void bbc_Click(object sender, EventArgs e)
{
Grid sl = gridlayout();
WebView webView = new WebView
{
Source = new UrlWebViewSource
{
Url = "http://www.bbc.co.uk/food/recipes/",
},
VerticalOptions = LayoutOptions.FillAndExpand
};
sl.Children.Add(webView);
this.Content = sl;
}
}
}
you need to set a span value if you want a control to go across multiple rows or columns
// add button to col 0 row 4
controlGrid.Children.Add (zeroButton, 0, 4);
// make the button span 2 columns
Grid.SetColumnSpan (zeroButton, 2);
How can I add Swipe to delete in my note list app.I am using xamarin forms. I have searched in xamarin forms samples but could not find it. I also tried the list view performance options with menuItem etc but I dont know how to adjust that in my code. Can anyone help me with this please?
My code is as follows:
public partial class MyPage
{
List<Note> notes;
string NotesFile {
get {
var documents = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
return System.IO.Path.Combine (documents, "notes.json");
}
}
public MyPage()
{
BuildContent();
LoadNotes ();
ReloadListContents ();
AddNoteButton.Clicked += (sender, args) => {
var note = new Note("typ...");
notes.Add(note);
EditNote(note);
};
NoteListView.ItemTapped += (sender, row) =>
{
NoteListView.SelectedItem = null;
Note note = (Note)row.Item;
EditNote(note);
};
buttonDelete.Clicked += (sender, args) =>{
notes.RemoveAt(0);
DisplayAlert("Delete", "Row deleted", "OK");
};
}
}
MyPage.cs
{
public ListView NoteListView = new ListView ();
public Button AddNoteButton;
public Button buttonDelete;
private void BuildContent()
{
AddNoteButton = new Button
{
Text = "Add New Note",
TextColor = Color.White,
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center
};
buttonDelete = new Button
{
Text = "Delete Note ",
TextColor = Color.White,
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center
};
Content = new StackLayout
{
BackgroundColor = Color.Black,
Children = {
new Label {
Text = "Note Taker",
TextColor = Color.White
},
NoteListView,
AddNoteButton,
buttonDelete
}
};
}
Im responding to this question in CS code rather than XAML (My Preferred) if anyone would like the Xaml response please drop a comment below and I'll write the XAML alongside the CS.
So to complete what you have asked in Xamarin.Forms on ListView elements you must first create the ViewCell that you would like to display the data in each cell in the ListView and give it context actions. Here is an example:
public class CustomViewCell : ViewCell
{
public CustomViewCell()
{
//instantiate each element we want to use.
var image = new CircleCachedImage
{
Margin = new Thickness(20, 10, 0, 10),
WidthRequest = App.ScreenWidth * 0.15,
HeightRequest = App.ScreenWidth * 0.15,
Aspect = Aspect.AspectFill,
BorderColor = Color.FromHex(App.PrimaryColor),
BorderThickness = 2,
HorizontalOptions = LayoutOptions.Center
};
var nameLabel = new Label
{
Margin = new Thickness(20, 15, 0, 0),
FontFamily = "Lato",
FontAttributes = FontAttributes.Bold,
FontSize = 17
};
var locationLabel = new Label
{
Margin = new Thickness(20, 0, 0, 5),
FontFamily = "Lato",
FontSize = 13
};
//Create layout
var verticaLayout = new StackLayout();
var horizontalLayout = new StackLayout() { BackgroundColor = Color.White };
//set bindings
nameLabel.SetBinding(Label.TextProperty, new Binding("Name"));
locationLabel.SetBinding(Label.TextProperty, new Binding("Location"));
image.SetBinding(CircleCachedImage.SourceProperty, new Binding("Image"));
//Set properties for desired design
horizontalLayout.Orientation = StackOrientation.Horizontal;
horizontalLayout.HorizontalOptions = LayoutOptions.Fill;
image.HorizontalOptions = LayoutOptions.End;
//add views to the view hierarchy
horizontalLayout.Children.Add(image);
verticaLayout.Children.Add(nameLabel);
verticaLayout.Children.Add(locationLabel);
horizontalLayout.Children.Add(verticaLayout);
//HERE IS THE MOST IMPORTANT PART
var deleteAction = new MenuItem { Text = "Delete", IsDestructive = true }; // red background
deleteAction.Clicked += async (sender, e) => {
//Here do your deleting / calling to WebAPIs
//Now remove the item from the list. You can do this by sending an event using messaging center looks like:
//MessagingCenter.Send<TSender,string>(TSender sender, string message, string indexOfItemInListview)
};
// add to the ViewCell's ContextActions property
ContextActions.Add(deleteAction);
// add to parent view
View = horizontalLayout;
}
}
Now you must do the following to your ListView:
listView = new ListView();
lstView.ItemTemplate = new DataTemplate(typeof(CustomViewCell));
In the same Content Page that you have the ListView you must also subscirbe to the MessagingCenter listening to the same parameters as set in the custom view cell as above. Please read the link provided if you have not used the MessagingCenter before. Inside of this method you must then remove the item from the listview with the index sent to this method.
If anyone needs any further explanations drop a comment below and Ill edit this post.
I am stuck on Navigating Pages in my app. I am beginner to Xamarin Form. What i am doing is i have a Master Details Page called master.cs by default it navigates to home page i.e. content page. I have created list view in other class page i.e. ModelClasses.cs now i want to navigate to other content pages while select listview item. i tried lot more things but not working.
HELP ME!!
MasterPage
public class master : MasterDetailPage
{
public master ()
{
Label header = new Label {
Text = "Master",
Font = Font.BoldSystemFontOfSize (20)
};
MenuStacklayout _MenuStacklayout = new MenuStacklayout ();
this.Master = new ContentPage{
Title=header.Text,
Content=_MenuStacklayout
};
this.Detail = new NavigationPage(new FTWHome());
// For Windows Phone, provide a way to get back to the master page.
if (Device.OS == TargetPlatform.WinPhone)
{
(this.Detail as ContentPage).Content.GestureRecognizers.Add(
new TapGestureRecognizer((view) =>
{
this.IsPresented = true;
}));
}
}
}
ModelClasses
MenuStacklayout Creates a Menu
public class MenuStacklayout : StackLayout
{
String[] homelinks = { "HOME" };
String[] healthlinks = { "I NEED HELP", "A MATE NEEDS HELP", "MOOD TRACKER", "HELPFUL ARTICLES" };
String[] entertainmentlinks = { "PHOTO OF THE DAY", "MAGZINE CONTENTS", "FTW TEAM" };
String[] aboutlinks = { "FTW PHILOSOPHY", "ABOUT FTW", "FTW STORE", "FTW SOCIAL" };
String[] joinftwlinks = { "JOIN FTW" };
String[] loginlinks = { "LOGIN" };
#region Menu Layout
public MenuStacklayout ()
{
ListView homelist = new ListView {
ItemsSource = menuitems._menuitems (homelinks),
ItemTemplate = new DataTemplate (typeof(ftwMenuCell))
};
homelist.RowHeight = 30;
homelist.ItemSelected+= navigatePage_onSelected;
StackLayout homeliststack = new StackLayout ();
homeliststack.Children.Add (homelist);
homelist.SeparatorVisibility = SeparatorVisibility.None;
//homeliststack.Padding = new Thickness (2, 5, 0, 0);
ListView healthlist = new ListView {
//Header = "HEALTH",
ItemsSource = menuitems._menuitems (healthlinks),
ItemTemplate = new DataTemplate (typeof(ftwMenuCell))
};
healthlist.RowHeight = 30;
healthlist.ItemSelected+=navigatePage_onSelected;
StackLayout healthliststack = new StackLayout ();
healthliststack.Children.Add (healthlist);
healthlist.SeparatorVisibility = SeparatorVisibility.None;
ListView entertainmentlist = new ListView {
//Header = "ENTERTAINMENT",
ItemsSource = menuitems._menuitems (entertainmentlinks),
ItemTemplate = new DataTemplate (typeof(ftwMenuCell))
};
entertainmentlist.RowHeight = 30;
entertainmentlist.ItemSelected+=navigatePage_onSelected;
StackLayout entertainmentliststack = new StackLayout ();
entertainmentliststack.Children.Add (entertainmentlist);
entertainmentlist.SeparatorVisibility = SeparatorVisibility.None;
ListView aboutlist = new ListView {
//Header = "ABOUT",
ItemsSource = menuitems._menuitems (aboutlinks),
ItemTemplate = new DataTemplate (typeof(ftwMenuCell))
};
aboutlist.RowHeight = 30;
aboutlist.ItemSelected+=navigatePage_onSelected;
StackLayout aboutliststack = new StackLayout ();
aboutliststack.Children.Add (aboutlist);
aboutlist.SeparatorVisibility = SeparatorVisibility.None;
ListView joinftwlist = new ListView {
ItemsSource = menuitems._menuitems (joinftwlinks),
ItemTemplate = new DataTemplate (typeof(ftwMenuCell))
};
joinftwlist.RowHeight = 30;
StackLayout joinftwliststack = new StackLayout ();
joinftwliststack.Children.Add (joinftwlist);
joinftwlist.SeparatorVisibility = SeparatorVisibility.None;
ListView loginlist = new ListView {
ItemsSource = menuitems._menuitems (loginlinks),
ItemTemplate = new DataTemplate (typeof(ftwMenuCell))
};
loginlist.RowHeight = 30;
loginlist.SeparatorVisibility = SeparatorVisibility.None;
loginlist.BackgroundColor = Color.Blue;
StackLayout loginstack = new StackLayout ();
loginstack.Children.Add (loginlist);
this.Spacing = 1;
this.BackgroundColor = Color.FromHex("#cccccc");
this.Padding = new Thickness (0, 65, 0, 0);
this.Orientation = StackOrientation.Vertical;
this.VerticalOptions = LayoutOptions.StartAndExpand;
this.Children.Add (homeliststack);
this.Children.Add (healthliststack);
this.Children.Add (entertainmentliststack);
this.Children.Add (aboutliststack);
this.Children.Add (joinftwlist);
this.Children.Add (loginstack);
}
}
ItemTemplate For Menu
public class ftwMenuCell : ViewCell
{
public ftwMenuCell ()
{
var nameLabel = new Label () {
FontFamily = "HelveticaNeue-Medium",
FontSize = 14,
FontAttributes=FontAttributes.Bold,
TextColor = Color.Black,
VerticalOptions=LayoutOptions.Center
};
nameLabel.SetBinding (Label.TextProperty, "_link");
var cellLayout = new StackLayout {
Spacing = 0,
Padding = new Thickness (10, 0, 0, 0),
VerticalOptions=LayoutOptions.FillAndExpand,
Orientation = StackOrientation.Horizontal,
Children = { nameLabel }
};
this.View = cellLayout;
}
}
public class _menulink
{
public string _link{ get; set; }
}
public static class menuitems
{
public static List<_menulink> _menuitems (string[] linkid)
{
List<_menulink> menulinklist = new List<_menulink> ();
foreach (var item in linkid) {
_menulink menulink = new _menulink ();
menulink._link = item;
menulinklist.Add (menulink);
}
return menulinklist;
}
}
i have respective content page for Every Listview Item.
THANKS IN ADVANCE!!
I can't see where you navigatePage_onSelected is declared but you could try something like
void navigatePage_onSelected(object sender, SelectedItemChangedEventArgs e) {
Navigation.PushModalAsync(new PageName());
}
Let me know if that works out for you :)
I have solved it !!
in my navigatePage_onSelected event handler which is declared in MenuStacklayout Class i put following code and it's working.
void navigatePage_onSelected(object sender, SelectedItemChangedEventArgs args){
_menulink menuitem = (_menulink)args.SelectedItem;
MasterDetailPage mstr = (MasterDetailPage)(Application.Current.MainPage); // My Application main page is a Masterpage so..
if (menuitem._link == "ABOUT FTW") {
mstr.Detail = new NavigationPage (new AboutFTW ());
}else if(menuitem._link == "I NEED HELP"){
mstr.Detail = new NavigationPage (new Entertainment ());
}else if(menuitem._link == "HOME"){
mstr.Detail = new NavigationPage (new FTWHome ());
}
// Show the detail page.
mstr.IsPresented = false;
}
While learning how to use Xamarin Forms and StackLayouts I'm having trouble rendering the items.
I'm trying to bind a collection of somethings to a StackLayout. The binding (more or less) works. The visual render is wrong.
For this question, I've picked some random thing (in this case, credit cards) to highlight my experimenting.
This is what I'm rending:
Notice how each custom row looks to be fixed height's or something?
Show me the code! Ok, so this is what I've done:
First, the page:
public class MyPage : ContentPage
{
protected override void OnAppearing()
{
var creditCards = new SomeFakeListOfCreditCards();
var stackLayout = new CreditCardStackLayout(creditCards);
Contet = stackLayout;
}
}
Now for the custom control...
public class CreditCardStackLayout : StackLayout
{
public CreditCardStackLayout(IEnumerable<CreditCard> creditCards)
{
// Note: credit cards can be null (because we don't have any).
CreateContent(creditCards);
}
private void CreateContent(IEnumerable<CreditCard> creditCards)
{
VerticalOptions = LayoutOptions.Center;
Children.Add(TitleLabel);
if (creditCards == null)
{
Children.Add(NoCreditCardLabel);
}
else
{
Children.Add(CreateCreateCardList(creditCards));
}
}
private static ListView CreateCreateCardList(IEnumerable<CreditCard> creditCards)
{
if (creditCards == null)
{
throw new ArgumentNullException("creditCards");
}
// Project the credit cards into a list view model.
var viewModel = creditCards.Select(x => new CreditCardViewModel(x));
return new ListView
{
ItemsSource = viewModel,
ItemTemplate = new DataTemplate(typeof(CreditCardViewCell))
};
}
private Label TitleLabel
{
get
{
return new Label
{
HorizontalOptions = LayoutOptions.Center,
Text = "A list of credit cards"
};
}
}
private Label NoCreditCardLabel
{
get
{
return new Label
{
Text = "You have no real credit cards on file."
};
}
}
}
So far so good.. Now for the binding..
public class CreditCardViewCell : ViewCell
{
protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();
var stackLayout = new StackLayout
{
BackgroundColor = new Color(46, 81, 163),
VerticalOptions = LayoutOptions.Center,
Children =
{
NameLabel,
TypeImage,
NumberLabel,
ExpiresOnLabel,
RemoveButton
}
};
View = stackLayout;
}
private Label NameLabel
{
get
{
var label = new Label
{
FontSize = 14
};
label.SetBinding(Label.TextProperty, "Name");
return label;
}
}
private Label NumberLabel
{
get
{
var label = new Label
{
FontSize = 14
};
label.SetBinding(Label.TextProperty, "Number");
return label;
}
}
private Label ExpiresOnLabel
{
get
{
var label = new Label
{
FontSize = 14
};
label.SetBinding(Label.TextProperty, "ExpiresOn");
return label;
}
}
private Image TypeImage
{
get
{
var creditCardModel = (CreditCardViewModel)BindingContext;
string fileName = null;
switch (creditCardModel.Type)
{
case "Visa":
fileName = "visa.png";
break;
default:
fileName = "mastercard.png";
break;
}
var image = new Image
{
Source = ImageSource.FromFile("Icons/" + fileName)
};
return image;
}
}
private Button RemoveButton
{
get
{
var button = new Button
{
//Image = "Icons/remove.png"
Text = "Remove"
};
button.Clicked += async (object sender, EventArgs e) =>
{
// TODO when I figure out how to do this stuff.
int i = 0;
i++;
};
return button;
}
}
}
}
Also, please do not suggest going to a XAML file, I'm trying to learn this stuff programmatically.
Side thought: I wish I could turn on borders so I can see how things are laid out.
Use ListView's HasUnevenRows property. Change this:
return new ListView
{
ItemsSource = viewModel,
ItemTemplate = new DataTemplate(typeof(CreditCardViewCell))
};
to:
return new ListView
{
HasUnevenRows = true,
ItemsSource = viewModel,
ItemTemplate = new DataTemplate(typeof(CreditCardViewCell))
};
By default Xamarin.Forms ListView row size is fixed and set to the same value for every row (RowHeight property). With this configuration row auto-sizing won't work, but it also gives best ListView performance.
You can auto-size rows by setting ListView's HasUnevenRows property to true. It allows modifying ViewCell size by setting ViewCell's RowHeight property (eg. in OnBindingContextChanged override). In newer Xamarin.Forms versions it also sizes ViewCells automatically (on older it worked only on Android).