I'm using this accordion control in WPF application : ayoutToolkit:Accordion.
I need to make dynamic content from database.
I tried like this:
private void RebuildView(Accordion accordion)
{
var scrollView = new ScrollViewer { VerticalScrollBarVisibility = ScrollBarVisibility.Auto};
var grid = new Grid
{
ShowGridLines = true,
ColumnDefinitions =
{
new ColumnDefinition(),
new ColumnDefinition(),
}
};
int i = 0;
foreach (AttributeModel item in ViewModel.Attributes)
{
RowDefinition row = new RowDefinition { Height = new GridLength(60) };
grid.RowDefinitions.Add(row);
var label = new Label { Content = item.label, Foreground = Brushes.Black, FontSize = 20 };
Grid.SetRow(label, i);
Grid.SetColumn(label,0);
grid.Children.Add(label);
i++;
}
scrollView.Content = grid;
accordion.ContentTemplate = new DataTemplate(scrollView);
}
but I'm not sure how to make it.
Related
I've been working on a Xamarin Forms project and I'm having trouble loading data into the Android application. It loads fine for iOS and UWP, but on Android it takes forever. This is happening on two different screens but I'm assuming the problem is the same. I'm sure there are better ways to load the data than what I am using.
This is the first screen I'm having trouble with on Android (screenshot from UWP):
It loads 15 products in each category into a horizontal scroller. The "See All" link loads all of the products in that category into a vertical scrolling grid. That's the second screen I'm having trouble with.
The code to load this view is:
var scroller = new TLScrollView
{
Orientation = ScrollOrientation.Horizontal,
ItemTemplate = new DataTemplate(() => ViewFactory.Merchandise.Invoke()),
HeightRequest = 320,
Padding = new Thickness(0, 0, 0, 10)
};
scroller.SetBinding(TLScrollView.ItemsSourceProperty, nameof(items));
scroller.ItemsSource = items.OrderByDescending(d => d.Cost).Take(15);
The ViewFactory code is:
public static Func<View> Merchandise { get; } = () =>
{
var mainGrid = new Grid() { WidthRequest = 250, Margin = 5 };
mainGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
mainGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(25, GridUnitType.Absolute) });
mainGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(25, GridUnitType.Absolute) });
mainGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(25, GridUnitType.Absolute) });
mainGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(35, GridUnitType.Absolute) });
var nameLabel = new Label() { Text = "Casket Name", LineBreakMode = LineBreakMode.TailTruncation, HorizontalTextAlignment = TextAlignment.Center };
var materialLabel = new Label() { Text = "MaterialName", HorizontalTextAlignment = TextAlignment.Center };
var costLabel = new Label() { Text = "Cost", HorizontalTextAlignment = TextAlignment.Center };
nameLabel.SetBinding(Label.TextProperty, "ItemName");
materialLabel.SetBinding(Label.TextProperty, "Material");
costLabel.SetBinding(Label.TextProperty, "CostFormatted");
GlobalModel globalModel = App.Current.MainPage.BindingContext as GlobalModel;
var catalogImage = new CachedImage
{
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand,
Aspect = Aspect.AspectFit,
LoadingPlaceholder = "MAFSLoader.gif",
CacheDuration = TimeSpan.FromDays(10),
RetryCount = 1,
RetryDelay = 100
};
catalogImage.BindingContextChanged += (s, o) => {
catalogImage.Source = null;
var item = catalogImage.BindingContext as CatalogItem;
if (item == null) return;
catalogImage.Source = item.SmallURL;
};
var buttonStyle = (Style)Application.Current.Resources["ButtonStyle"];
var addToCartButton = new Button { Text = "Add to Cart", BackgroundColor = Color.FromHex("#486E8E"), WidthRequest = 250, Style = buttonStyle };
addToCartButton.SetBinding(Button.CommandParameterProperty, "ItemID");
var imgTapGesture = new TapGestureRecognizer()
{
Command = new Command(() =>
{
if (addToCartButton.CommandParameter == null)
{
addToCartButton.SetBinding(Button.CommandParameterProperty, "ItemId");
}
var dictionary = new Dictionary<string, string>();
dictionary.Add(globalModel.CurrentFuneralHomeKey, addToCartButton.CommandParameter.ToString());
globalModel.ProductDetail.Execute(dictionary);
})
};
catalogImage.GestureRecognizers.Add(imgTapGesture);
addToCartButton.Clicked += new EventHandler(async delegate (Object o, EventArgs a)
{
var button = ((Button)o);
globalModel.AddToCart.Execute(button.BindingContext);
if (button.BindingContext.GetType() == typeof(Data.Corner))
{
await App.Current.MainPage.DisplayAlert("Shopping Cart", "You've added " + (button.BindingContext as Data.Corner).ItemName + " to your cart.", null, "OK");
}
});
mainGrid.Children.Add(catalogImage, 0, 0);
mainGrid.Children.Add(nameLabel, 0, 1);
mainGrid.Children.Add(materialLabel, 0, 2);
mainGrid.Children.Add(costLabel, 0, 3);
mainGrid.Children.Add(addToCartButton, 0, 4);
return mainGrid;
};
If anyone could point me in the right direction I'd be very grateful!
Interesting. I've just gone through the implementation of the TLSrollview. It looks like there is no recycling of elements and maybe lack some optimization (I can see that only if I debug). I see two options :
option 1 : Create a listview with recycling strategy on. For better performance, set also the row height. One item of your listview would be one row. The advantage of a listview is the performance gain from the recycling strategy (especially on Android). Note that on iOS and Android, it might be better to set it on or not.
option 2 : Create a custom layout. That might be a little overkill.
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;
}