I have a simple page with a ListView like this
<?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="ListViewDemo.MainPage">
<StackLayout>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Text="From" />
<DatePicker x:Name="fromPicker" Grid.Row="1" />
<Label Text="To" Grid.Column="1" />
<DatePicker x:Name="toPicker" Grid.Column="1" Grid.Row="1" />
</Grid>
<ListView>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<Label Text="{Binding FromDate}" />
<Label Text="{Binding ToDate}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
When the Date is changed I want to scroll to the Event, that is closest to the current Date, but I get an UnhandledException when I use ScrollTo on UWP, and iOS just do not scroll.
I was thinking of using ItemAppearing, but is it trustable, if I have enough events on the list?
If I use await Task.Delay(500) I do not get the UnhandledException, but instead the content jumps on my screen.
Is there any solution to this problem?
public void SetEvents(params CalenderEventDto[] events)
{
var dateToScrollTo = DateTime.Now.Date;
var scrollToEvent = events?.OrderBy(x => x.Start.Date)?.FirstOrDefault(c => c.Start.Date >= dateToScrollTo || c.End.Date >= dateToScrollTo );
var orderedEvents = events.GroupBy(x => x.Start.Date).OrderBy(x => x.Key);
_calendarEvents.Clear();
foreach (var groupedEvents in orderedEvents)
{
foreach (var calendarEvent in groupedEvents)
{
_calendarEvents.Add(calendarEvent);
}
}
//await Task.Delay(450);
Device.BeginInvokeOnMainThread(() => lstCalendar.ScrollTo(scrollToEvent, ScrollToPosition.Start, false));
}
EDIT
I figured out, the problem is on iOS too
I figured out, if I moved the SetEvents from the constructor to OnAppearing it works
Related
I am quite new to this, but I am trying to figure out how to dynamically add entries with a button click.
I am creating new entries with each button click but my issue is that the entries are placed under the button instead of ontop of it.
Here is how my app looks like:
[![enter image description here][1]][1]
By clicking the `Add Ingredient` button, I want to add a new entry.
This is what the front end looks like:
<?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="EasyChef.Views.AboutPage"
xmlns:vm="clr-namespace:EasyChef.ViewModels"
Title="{Binding Title}">
<ContentPage.BindingContext>
<vm:AboutViewModel />
</ContentPage.BindingContext>
<ContentPage.Resources>
<ResourceDictionary>
<Color x:Key="Accent">#96d1ff</Color>
</ResourceDictionary>
</ContentPage.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackLayout BackgroundColor="{StaticResource Accent}" VerticalOptions="FillAndExpand" HorizontalOptions="Fill">
<StackLayout Orientation="Horizontal" HorizontalOptions="Center" VerticalOptions="Center">
<ContentView Padding="0,40,0,40" VerticalOptions="FillAndExpand">
<Label Text="EasyChef" TextColor="Black" FontSize="24" FontAttributes="Bold" Margin="10"/>
</ContentView>
</StackLayout>
</StackLayout>
<ScrollView Grid.Row="1">
<StackLayout Orientation="Vertical" Padding="30,24,30,24" Spacing="10">
<Label Text="Simply select ingredients!" FontSize="Title"/>
<StackLayout x:Name="EntriesStackLayout">
<Grid VerticalOptions="CenterAndExpand" Margin="20" RowSpacing="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Entry Placeholder="Eg. Eggs" x:Name="EntryTag" Grid.Row="0"/>
<Button Text="Add Ingredient" Grid.Row="1" Clicked="Button_Clicked"/>
</Grid>
</StackLayout>
<CheckBox />
</StackLayout>
</ScrollView>
</Grid>
</ContentPage>
And the back end()
public partial class AboutPage : ContentPage
{
int x = 1;
public AboutPage()
{
InitializeComponent();
}
private void Button_Clicked(object sender, EventArgs e)
{
AddEntry(EntriesStackLayout, "Ingredient " + x.ToString());
x++;
}
private void AddEntry(StackLayout sl, string name)
{
Entry entry = new Entry()
{
Placeholder = name,
};
sl.Children.Add(entry);
}
}
My preferred solution would be to create new entries with each button click, but I am happy with having default entries and unhiding them in order with a click.
A simple method is to move the Button to the outside of the StackLayout(StackLayout x:Name="EntriesStackLayout") and below the StackLayout.
Please refer to the following code:
<ScrollView Grid.Row="1">
<StackLayout Orientation="Vertical" Padding="30,24,30,24" Spacing="10">
<Label Text="Simply select ingredients!" FontSize="Title"/>
<StackLayout x:Name="EntriesStackLayout">
<Grid VerticalOptions="CenterAndExpand" Margin="20" RowSpacing="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Entry Placeholder="Eg. Eggs" x:Name="EntryTag" Grid.Row="0"/>
<!--<Button Text="Add Ingredient" Grid.Row="1" Clicked="Button_Clicked"/>-->
</Grid>
</StackLayout>
<!--move button here-->
<Button Text="Add Ingredient" Grid.Row="1" Clicked="Button_Clicked"/>
<CheckBox />
</StackLayout>
</ScrollView>
Good morning!
I've a big problem with ListViews in Xamarin Forms: my items aren't shown.
This is my xml code:
<?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:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="KOTC.Views.News">
<ContentPage.Content>
<StackLayout>
<ListView x:Name="list" HasUnevenRows="true" IsVisible="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Padding="20">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Text ="{Binding title}" Grid.Row="0" VerticalOptions="CenterAndExpand" FontSize="10" TextColor="Black"/>
<Label Text="{Binding date}" Grid.Row="1" FontSize="10"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
and this is my class constructor:
public News()
{
InitializeComponent();
ObservableCollection<ListNewsItem> listNews = new ObservableCollection<ListNewsItem>();
RemoteDBConnection conn = new RemoteDBConnection(QUERY);
conn.Connect();
List<Models.News> news = conn.ExecuteQueryWithResponse(QUERY);
for (int i = 0; i < news.Count; i++)
{
ListNewsItem item = new ListNewsItem
{
date = news[i].publicationDate,
title = news[i].title
};
listNews.Add(item);
}
list.ItemsSource = listNews;
}
In this moment method ExecuteQueryWithResponse() returns 3 items, that are detected by ListView, in fact when I start the app, I see 3 ViewCells. The problem is that these viewcells are empty, they're not showing data.
Someone can help me?
I can't believe I have spent a day trying to get this to work! I began developing in Xamarin.Forms last month and for the most part things have been going pretty smooth. My background is ASP.Net MVC and Windows Forms so the MVVM concept is new to me.
The issue that I am having is very frustrating and seems silly really. I imagine it could be my implementation possibly because I am not using MVVM but am performing all binding in the code behind? I have a page that has a search box and a ListView controll. Each of the items in the ListView is fairly simple... it only consists of a few labels and a switch. The ListView is bound every time someone performs a search. The problem that I am having is that every time someone performs a search it refreshes the Model everyting is bound to... this in turn triggers the Switches Toggle Event. Within the Toggle Event I have code that would update the database when the value is changed so I do not want this fired off every time the model changes. It is very frustrating as there does not appear to be a Click Event. See Xaml and the Method I am using below:
public async void SearchItems()
{
PageLoaded = false;
if(string.IsNullOrEmpty(this.txtSearch.Text)) { return; }
this.LoadSearch.IsRunning = true;
// Populate Locations For Item
string ItemType = HttpUtility.UrlEncode(this.SelectItemType.SelectedItem.ToString());
string Search = HttpUtility.UrlEncode(this.txtSearch.Text.ToLower());
string url = string.Format("https://test.com/api/LocationsSearch?itemType={0}&search={1}", ItemType, Search);
LocationsList = new List<Locations>();
var json = await func.GetIBApi(url);
LocationsList = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Locations>>(json);
this.ItemsList.ItemsSource = LocationsList;
this.LoadSearch.IsRunning = false;
PageLoaded = true;
}
Toggle Event:
private async void Switch_Toggled(object sender, ToggledEventArgs e)
{
try
{
if (PageLoaded)
{
bool isPrimary = e.Value;
ViewCell cell = (sender as Switch).Parent.Parent.Parent as ViewCell;
var location = cell.BindingContext as Locations;
string display = "";
if (isPrimary)
{
display = "Are you sure you want to make this the 'Primary Location'?";
}
else
{
display = "Are you sure you want to unset this as the 'Primary Location'? Note: Make sure you set another location as the 'Primary' on this PartNumber!";
}
var result = await App.Current.MainPage.DisplayAlert("Primary Change Confirmation", display, "Yes", "No");
if (result)
{
string url = string.Format("https://test.com/api/LocationsSearch?partNumber={0}&location={1}&isPrimary={2}", location.ID, location.Location, isPrimary);
var json = await func.PostIBApi(url);
await Navigation.PopModalAsync();
}
}
}
catch (Exception e2)
{
}
}
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"
x:Class="IBMobile.Views.LocationsPage"
xmlns:local2="clr-namespace:FontAwesome"
Visual="Material">
<ContentPage.IconImageSource>
<FontImageSource FontFamily="{StaticResource FontAwesomeSolid}" Glyph="{x:Static local2:IconFont.MapMarkerAlt}" />
</ContentPage.IconImageSource>
<ContentPage.Content>
<StackLayout Padding="25">
<Picker x:Name="SelectItemType" SelectedIndexChanged="SelectItemType_SelectedIndexChanged" />
<SearchBar x:Name="txtSearch" SearchButtonPressed="TxtSearch_SearchButtonPressed" Placeholder="Search..." FontSize="Title"></SearchBar>
<ActivityIndicator Color="#007D5D" IsRunning="false" x:Name="LoadSearch" HorizontalOptions="Center" />
<ListView x:Name="ItemsList" ItemTapped="ItemsList_ItemTapped" HasUnevenRows="True" BackgroundColor="White">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout VerticalOptions="FillAndExpand">
<Grid VerticalOptions="FillAndExpand" Padding="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"></ColumnDefinition>
<ColumnDefinition Width="3*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Label TextColor="#007D5D" Text="{Binding ViewID}" FontSize="Title" VerticalTextAlignment="Center" Grid.Column="0" Grid.Row="0"></Label>
<Label TextColor="#007D5D" Text="{Binding Location}" FontSize="Title" VerticalTextAlignment="Center" Grid.Column="1" Grid.Row="0"></Label>
<Label Text="Primary" Grid.Column="2" Grid.Row="0"></Label>
<Switch IsToggled="{Binding IsPrimary}" x:Name="Toggle1" ThumbColor="#007D5D" Grid.Column="2" Grid.Row="1" Toggled="Switch_Toggled"/>
<Label Text="{Binding Description}" Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2"></Label>
<Label Text="{Binding Message}" Grid.Column="0" Grid.Row="2" Grid.ColumnSpan="3" FontSize="Small" TextColor="Red"></Label>
</Grid>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
if (PageLoaded)
{
//entered handler
bool isPrimary = e.Value; //we are invoking the handler again from inside itsself
// all the mess comes from this
Use another lock:
if (PageLoaded && !_internal)
{
//entered handler
_internal=true;
bool isPrimary = e.Value;
_internal=false;
I am currently working with a list that i bind through my viewmodel and then a service.
In the list i bind an image and a label. I can successfully get the label binded, but the image does not show. The reason for this seems to be because i change the bindingcontext in the grid where the image is nested inside. I change the bindingcontext in order to get an accurate width for the image.
If i move the image outside the grid, then it shows, so now i am trying to get the bindingcontext in order again.
What i tried to do with the image was to add a new bindingcontext
BindingContext="{x:Reference Name=gridFollowers}" Source="{Binding image}"
where gridFollowers is what i name my stacklayout where the original binding is made, but unfortunately the image still does not show.
here is the full code:
<StackLayout x:Name="gridFollowers"
BindableLayout.ItemsSource="{Binding headerService.CurrentHeader}">
<BindableLayout.ItemTemplate >
<DataTemplate>
<Grid WidthRequest="75">
<Grid.RowDefinitions>
<RowDefinition Height="8*" />
<RowDefinition Height="2*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="7.5*" />
</Grid.ColumnDefinitions>
<Grid
Grid.Row="0"
Grid.Column="0"
BindingContext="{x:Reference Name=headerImage}"
WidthRequest="{Binding Height}">
<ffimageloading:CachedImage
x:Name="headerImage" BindingContext="{x:Reference Name=gridFollowers}"
Source="{Binding image}" />
</Grid>
<Label Grid.Row="1" Grid.Column="0"
Text="{Binding firstname}" />
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
How can i make it so the image shows?
I try your code and modify some code as following, please replace your code.
<Grid
Grid.Row="0"
Grid.Column="0"
WidthRequest="{Binding Height, Source={x:Reference headerImage}}">
<ffimageloading:CachedImage x:Name="headerImage" Source="{Binding image}" />
</Grid>
Update:
please check headerService.CurrentHeader data.
Please check if binding viewmodel to page.cs bindingcontext by code behind.
<Grid.RowDefinitions>
<RowDefinition Height="8*" />
<RowDefinition Height="2*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="7.5*" />
</Grid.ColumnDefinitions>
<Grid
Grid.Row="0"
Grid.Column="0"
WidthRequest="{Binding Height, Source={x:Reference headerImage}}">
<ffimageloading:CachedImage x:Name="headerImage" Source="{Binding image}" />
</Grid>
<Label
Grid.Row="1"
Grid.Column="0"
Text="{Binding firstname}" />
</Grid>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
public partial class Page8 : ContentPage
{
public ObservableCollection<imagemodel> models { get; set; }
public Page8 ()
{
InitializeComponent ();
models = new ObservableCollection<imagemodel>()
{
new imagemodel(){firstname="first image", image="a1.jpg"},
new imagemodel(){firstname="second image",image="a2.jpg"}
};
this.BindingContext = this;
}
}
public class imagemodel
{
public string firstname { get; set; }
public string image { get; set; }
}
Please see the XAML below:
<?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:App1"
x:Class="App1.MainPage">
<ContentPage.BindingContext>
<local:PersonViewModel />
</ContentPage.BindingContext>
<StackLayout>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="20" />
</Grid.RowDefinitions>
<Label Grid.Column="1" Text="First Name" />
<Label Grid.Column="2" Text="Surname" />
<Label Grid.Column="3" Text="Date Of Birth" />
</Grid>
<ListView x:Name="listView" ItemsSource="{Binding people}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Label Grid.Column="1" Text="{Binding FirstName}" />
<Label Grid.Column="2" Text="{Binding Surname}" />
<Label Grid.Column="3" Text="{Binding Age}" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
and the View Model:
public class PersonViewModel
{
public ObservableCollection<Person> people = new ObservableCollection<Person>();
public PersonViewModel()
{
people.Add(new Person { Age = 36, FirstName = "Andrew", Surname = "Smith" });
people.Add(new Person { Age = 65, FirstName = "David", Surname = "White" });
people.Add(new Person { Age = 39, FirstName = "Bert", Surname = "Edwards" });
}
}
Only the column headings display. Why does the data not display?
I have spent all afternoon trying to get this to work. I have read lots of different answers, however I still cannot get any data to display.
You are missing the Grid Column Definitions (if it is the same as the header, so your xaml should look like this:
<StackLayout>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="* />
<ColumnDefinition Width="* />
<ColumnDefinition Width="* />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="20" />
</Grid.RowDefinitions>
<Label Grid.Column="1" Text="First Name" />
<Label Grid.Column="2" Text="Surname" />
<Label Grid.Column="3" Text="Date Of Birth" />
</Grid>
<ListView x:Name="listView" ItemsSource="{Binding people}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="* />
<ColumnDefinition Width="* />
<ColumnDefinition Width="* />
</Grid.ColumnDefinitions>
<Label Grid.Column="1" Text="{Binding FirstName}" />
<Label Grid.Column="2" Text="{Binding Surname}" />
<Label Grid.Column="3" Text="{Binding Age}" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>