I have a pretty straight forward question.
With this code, I create new entries whenever i click a button:
XAML
<Button Text="Add Ingredient" Grid.Row="1" Clicked="Button_Clicked"/>
Code-behind
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);
}
I want to know what could I do to then remove these entries in order. For last to first?
This is what the app looks like:
I want to know what could I do to then remove these entries in order.
For last to first?
For your problem, you can remove the last element one by one in your StackLayout(EntriesStackLayout).
Please refer to the following code:
private void Button_Clicked_Remove(object sender, EventArgs e)
{
var element = EntriesStackLayout.Children.LastOrDefault();
if (element!=null) {
EntriesStackLayout.Children.Remove(element);
}
}
YouPage.xaml
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackLayout 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"/>
</Grid>
</StackLayout>
<Button Text="Add Ingredient" Grid.Row="1" Clicked="Button_Clicked"/>
<Button Text="Relete Ingredient" Grid.Row="1" Clicked="Button_Clicked_Remove"/>
<CheckBox />
</StackLayout>
</ScrollView>
</Grid>
Note:
Make sure to add a null judgement, or the app may crash:
if (element!=null) {
EntriesStackLayout.Children.Remove(element);
}
To remove an element from a layout
sl.Children.Remove(element);
If you don’t already have a reference to the element
var element = sl.Children.LastOrDefault();
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>
I have a Content Page in which I want to show an invoice, for that I have two listviews.
The first one contains the name of the customer, the date and the total cost.
The thing is to get the total cost I have used Shell navigation with parameters and it works fine just not in the listview.
So here is my ViewModel
[QueryProperty(nameof(Total), "total")]
public class InvoiceViewModel : BindableObject
{
string _total;
public string Total
{
get => _total;
set
{
_total = Uri.UnescapeDataString(value ?? string.Empty);
OnPropertyChanged();
}
}
public InvoiceViewModel()
{
_oListOrders = new ObservableCollection<CrOrder>();
GetListCart();
}
private ApiService _apiService = new ApiService();
public List<Invoice> _oListCart = new List<Invoice>();
public ObservableCollection<CrOrder> _oListOrders;
public List<Invoice> ListCart
{
get => _oListCart;
set
{
_oListCart = value;
OnPropertyChanged();
}
}
private async void GetListCart()
{
// call database here
var customerId = Convert.ToInt32(CurrentPropertiesService.GetCustomer());
var customer = await _apiService.GetCustomerById(customerId, CurrentPropertiesService.GetToken());
_oListCart.Add(new Invoice
{
Name = customer.Data.Name,
Date = DateTime.UtcNow,
Total = Convert.ToDecimal(_total),
ListOrders = await GetListOrders()
});
}
private async Task<ObservableCollection<CrOrder>> GetListOrders()
{
// call database here
var cartId = Convert.ToInt32(CurrentPropertiesService.GetCart());
var orders = await _apiService.GetOrdersByCart(cartId, CurrentPropertiesService.GetToken());
ObservableCollection<CrOrder> collection = new ObservableCollection<CrOrder>(orders.Data);
return collection;
}
}
Here is what I have in my View
<ContentPage.Content>
<StackLayout BackgroundColor="#A7A7A7">
<Label Text="{Binding Total}" VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand"></Label>
<ListView x:Name="ListViewCart" ItemsSource="{Binding ListCart}" HasUnevenRows="True" IsPullToRefreshEnabled="False" >
<ListView.ItemTemplate>
<DataTemplate x:DataType="model:Invoice">
<ViewCell>
<Frame HasShadow="True" Margin="2" BorderColor="Gray">
<Grid Margin="0" HorizontalOptions="FillAndExpand" VerticalOptions="Center" HeightRequest="150" RowSpacing="0" ColumnSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*"/>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Text="Nombre del Cliente:" VerticalOptions="Start"/>
<Label Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2" Text="{Binding Name}" VerticalOptions="Start"/>
<Label Grid.Row="1" Grid.Column="0" Text="Fecha Compra:" VerticalOptions="Start"/>
<Label Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" Text="{Binding Date}" VerticalOptions="Start"/>
<Label Grid.Row="2" Grid.Column="0" Text="Monto Total:" VerticalOptions="Start"/>
<Label Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" Text="{Binding Total, StringFormat='{0:N2}€'}" VerticalOptions="Start"/>
<Label Grid.Row="3" Grid.ColumnSpan="3" Text="Detalle Compra" VerticalOptions="Start"/>
<BoxView Grid.Row="4" Grid.ColumnSpan="3" Color="Gray" HeightRequest="2" HorizontalOptions="Fill" />
<Label Grid.Row="5" Grid.Column="0" Text="Nombre" VerticalOptions="Start" TextColor="#9C2424"/>
<Label Grid.Row="5" Grid.Column="1" Text="Monto" VerticalOptions="Start" TextColor="#9C2424"/>
<Label Grid.Row="5" Grid.Column="2" Text="Cantidad" VerticalOptions="Start" TextColor="#9C2424"/>
<StackLayout Grid.Row="6" Grid.ColumnSpan="3" Margin="0" Padding="0">
<ListView x:Name="ListViewOrders" ItemsSource="{Binding ListOrders}" HasUnevenRows="True" IsPullToRefreshEnabled="False" >
<ListView.ItemTemplate>
<DataTemplate x:DataType="model:CrOrder">
<ViewCell IsEnabled="False">
<Grid RowSpacing="0" ColumnSpacing="0" Margin="0" MinimumHeightRequest="50">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*"/>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Text="{Binding Reference}" TextColor="Black" VerticalOptions="Center" FontSize="12" />
<Label Grid.Row="0" Grid.Column="1" Text="{Binding Price, StringFormat='{0:N2}€'}" TextColor="Black" VerticalOptions="End" FontSize="12" />
<Label Grid.Row="0" Grid.Column="2" Text="{Binding Quantity}" TextColor="Black" VerticalOptions="End" FontSize="12"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>...
And on my ContentPage I don't have anything
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class InvoicePage : ContentPage
{
public InvoicePage()
{
InitializeComponent();
//BindingContext = new InvoiceViewModel();
}
}
So on my View I have put a label to check what I thought was happening. So the label shows right the total but when I use the ListView binging it doesn't work I don't know why it is null there.
As you can see the label works fine but where it sais "Monto Total" it shows nothing. Please help I don't know what is going on. Thanks.
EDIT
I tried naming the Total property different and then when I add my Invoice entity to my list I do this
Total = Convert.ToDecimal(TotalCart),
But it isn't working eitherway. I don't know why the first time it returns the value fine but the second it doesn't.
After debbuging I have realized when getting the total property that the first time when GetListCart is being called the value is null and the second time, when the label text is set it returns the correct value. Why is this happening?
I'm having an issue figuring out how to remove an item from my project while using the same button as I use to perform another task. To sum it up, I'm working on a project where I have a bunch of events a user can like/dislike. What I'm having issues with is trying to figure out how to remove the event from my project once the user has liked the event using the 'like' button. Essentially I want the 'like' button to perform 2 things, one being when its pressed setting it to "true" which is already doing that, but also I want it to remove the event from screen once it's liked.
Here is my XAML:
<StackLayout VerticalOptions="FillAndExpand">
<Grid RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="1*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image x:Name="LblEventImage"
Aspect="Fill"
HeightRequest="350" />
<BoxView BackgroundColor="Black"
HeightRequest="350"
Opacity="0.3" />
<Image Source="BackIconOrg.png"
Margin="5,40,0,0"
HorizontalOptions="Start"
VerticalOptions="Start"
Grid.Row="0">
<Image.GestureRecognizers>
<TapGestureRecognizer x:Name="ImgBack" Tapped="backButton_Clicked"/>
</Image.GestureRecognizers>
</Image>
</Grid>
<Frame VerticalOptions="FillAndExpand"
IsClippedToBounds="False"
BackgroundColor="#263A4F"
Margin="0,-40,0,0"
CornerRadius="25"
HasShadow="False">
<StackLayout Margin="0,-50,0,0">
<Grid HeightRequest="200"
VerticalOptions="Start">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4*" />
<ColumnDefinition Width="6*"/>
</Grid.ColumnDefinitions>
<StackLayout Grid.Column="0"
Padding="5"
Spacing="5"
Margin="0,40,0,0">
<Label x:Name="LblEventName"
TextColor="#fc4600"
FontSize="Large"
FontFamily="TTBold"
FontAttributes="Bold"/>
<StackLayout Orientation="Horizontal"
Spacing="0">
<Frame BackgroundColor="#8B93A6"
BorderColor="#8B93A6"
Padding="8"
CornerRadius="15">
<Label TextColor="White"
x:Name="LblEventCategory"
FontFamily="TTNorms"/>
</Frame>
</StackLayout>
<StackLayout Orientation="Vertical" Grid.ColumnSpan="3">
<Label x:Name="LblEventCity"
TextColor="White"
FontFamily="TTNorms"/>
<Label x:Name="LblEventState"
TextColor="White"
FontFamily="TTNorms"/>
</StackLayout>
<!--<Label x:Name="LblLanguage"
TextColor="White" />
<Label x:Name="LblDuration"
TextColor="White" />-->
</StackLayout>
</Grid>
<Label Text="Details:"
FontSize="Medium"
Margin="0,20,0,0"
TextColor="White"
FontFamily="TTNorms"/>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.65*" />
<ColumnDefinition Width="0.35*" />
</Grid.ColumnDefinitions>
<Label Text="Scheduled Date:"
TextColor="White"
Grid.Row="0"
Grid.Column="0"
FontFamily="TTNorms"/>
<Label Text="August 20, 2021"
TextColor="#8B93A6"
Grid.Row="1"
Grid.Column="0"
FontFamily="TTNorms"/>
<Label Text="Group Size:"
TextColor="White"
Grid.Row="0"
Grid.Column="1"
FontFamily="TTNorms"/>
<Label x:Name="LblEventGroupSize"
TextColor="#8B93A6"
Grid.Row="1"
Grid.Column="1"
FontFamily="TTNorms"/>
<Label Text="Paid:"
TextColor="White"
Grid.Row="2"
Grid.Column="0"
FontFamily="TTNorms"/>
<Label x:Name="LblEventPay"
TextColor="#8B93A6"
Grid.Row="3"
Grid.Column="0"
FontFamily="TTNorms"/>
</Grid>
<BoxView BackgroundColor="#8B93A6"
HeightRequest="1" />
<Label Text="Description"
TextColor="White"
FontFamily="TTNorms"/>
<Label x:Name="LblEventDescription"
TextColor="#8B93A6"
FontFamily="TTNorms"/>
<StackLayout Orientation="Horizontal"
HorizontalOptions="Center"
VerticalOptions="Center"
Spacing="60"
Margin="0,30,0,0">
<Image Source="LikeButton.png"
HeightRequest="150">
<Image.GestureRecognizers>
<TapGestureRecognizer x:Name="likedevent" Tapped="likeButton_Clicked" />
</Image.GestureRecognizers>
</Image>
<Image Source="DislikeButton.png"
HeightRequest="150">
<Image.GestureRecognizers>
<TapGestureRecognizer x:Name="dislikeevent" Tapped="dislikeevent_Tapped"/>
</Image.GestureRecognizers>
</Image>
</StackLayout>
</StackLayout>
</Frame>
</StackLayout>
</ContentPage.Content>
CS:
public partial class MatchDetail : ContentPage
{
private Event event1;
public MatchDetail(int eventId)
{
InitializeComponent();
GetEventDetail(eventId);
}
private async void GetEventDetail(int eventId)
{
event1 = await ApiService.GetEventById(eventId);
LblEventName.Text = event1.Name;
LblEventDescription.Text = event1.Description;
LblEventCity.Text = event1.City;
LblEventImage.Source = event1.FullImageUrl;
LblEventCategory.Text = event1.Category;
LblEventState.Text = event1.State;
LblEventGroupSize.Text = event1.GroupSize.ToString();
LblEventPay.Text = event1.PayTrueFalse;
}
private async void likeButton_Clicked(object sender, EventArgs e)
{
var likedEvent = new Result()
{
Name = LblEventName.Text,
UserId = Preferences.Get("userId", 0),
LikeTrueFalse = "True"
};
if (event1.LikeTrueFalse == "True")
{
//RemoveEvent
}
var response = await ApiService.LikedEvents(likedEvent);
if (response)
{
await DisplayAlert("", "Your event has been liked", "Ok");
}
else
{
await DisplayAlert("Oops", "something went wrong", "cancel");
}
}
private void backButton_Clicked(object sender, EventArgs e)
{
Navigation.PopModalAsync();
}
in your main page
MessagingCenter.Subscribe<object, int>(this, "RemoveEvent", (sender,id) =>
{
// do whatever to remove event "id" here
});
then in your detail page, after you have marked it as a favorite
Messaging.Center.Send<object, int>(this, "RemoveEvent", eventId);
I'm looking for the best way to change the content of a page, without navigating to a new one.
I tried having two stacklayouts, and on a button press I'd change the IsVisible and IsEnabled properties of each stack layout. Although this worked, I was left with a small white gap at the end of each layout (I believe this is a Xamarin.Forms bug).
What would be the best way to accomplish this task? Is there anything built into Xamarin.Forms that can do this that I have missed?
Here is a little sketch design for you to see what I mean:
Before suggesting I use tabs, I'll add that I already have tabs in the application, the sketch doesn't show that though. I need this navigation to work on only ONE page.
The code I used before, that didn't work is:
(Before anybody mentions the poor naming conventions and lack of content, I had to strip it all out as it's code written for an employer.
C#:
private void Button1_Clicked(object sender, EventArgs e)
{
Content2.IsVisible = false;
Content2.IsEnabled = false;
Content1.IsVisible = true;
Content1.IsEnabled = true;
}
private void Button2_Clicked(object sender, EventArgs e)
{
Content2.IsVisible = true;
Content2.IsEnabled = true;
Content1.IsEnabled = false;
Content1.IsVisible = false;
}
XML:
<ScrollView x:Name="content1" VerticalOptions="FillAndExpand" BackgroundColor="#f2f2f2">
<StackLayout Spacing="0">
<StackLayout Orientation="Horizontal" BackgroundColor="White" Padding="20,20,20,20" HorizontalOptions="FillAndExpand">
<StackLayout>
<Label Text="text:" FontFamily="{StaticResource BoldFont}"/>
<StackLayout Orientation="Horizontal">
<Image x:Name="content1image" HeightRequest="25" WidthRequest="25"/>
<Label x:Name="content1label" FontFamily="{StaticResource Font}" FontSize="27" TextColor="#969696"/>
</StackLayout>
</StackLayout>
<StackLayout HorizontalOptions="FillAndExpand">
<Entry x:Name="content1Entry" Keyboard="Numeric" Margin="0,25,0,0" Placeholder="0.00000000" FontFamily="{StaticResource Font}" FontSize="27" HorizontalOptions="FillAndExpand" HorizontalTextAlignment="End" TextColor="#969696"/>
<Label x:Name="content1Label2" FontSize="14" FontFamily="{StaticResource Font}" HorizontalOptions="FillAndExpand" HorizontalTextAlignment="End" TextColor="#969696"/>
</StackLayout>
</StackLayout>
<StackLayout Padding="20,30,20,0" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<Label Text="content1Label3" FontFamily="{StaticResource Font}"/>
<StackLayout Orientation="Horizontal">
<Button x:Name="content1button" Image="image.png" BackgroundColor="Transparent" HorizontalOptions="Start" Margin="0" WidthRequest="25" HeightRequest="25"/>
<Entry x:Name="content1Entry2" FontFamily="{StaticResource Font}" FontSize="12" HorizontalOptions="FillAndExpand" HorizontalTextAlignment="End"/>
</StackLayout>
</StackLayout>
<StackLayout VerticalOptions="EndAndExpand" Padding="0,-1,0,0">
<Label x:Name="content1Label4" FontSize="19" HorizontalOptions="CenterAndExpand" FontFamily="{StaticResource Font}"/>
<Label x:Name="content1Label5" FontSize="12" TextColor="#b6b6b6" HorizontalOptions="CenterAndExpand" FontFamily="{StaticResource Font}"/>
<Button x:Name="content1Button2" VerticalOptions="End" HorizontalOptions="FillAndExpand" BorderRadius="25" BackgroundColor="#2r432d" BorderColor="#2r432d" TextColor="White" FontFamily="{StaticResource Font}" FontSize="20" BorderWidth="3" Margin="10,10,10,10"/>
</StackLayout>
</StackLayout>
I have not had very much success using Stacklayouts. Grids however has a lot of customizability and in my case it expands to fill all the area that you wish for.
This is how I would do it.
Xaml
<Grid x:Name="Grid1" IsVisible="False" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand">
<Label FontSize="Medium" Text="Grid1 Label"/>
</Grid>
<Grid Grid.Row="1" HeightRequest="100" WidthRequest="375" VerticalOptions="StartAndExpand" HorizontalOptions="CenterAndExpand">
<Button x:Name="btnGrid1"/>
</Grid>
</Grid>
<Grid x:Name="Grid2" IsVisible="False" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand">
<Label FontSize="Medium" Text="Grid2 Label"/>
</Grid>
<Grid Grid.Row="1" HeightRequest="100" WidthRequest="375" VerticalOptions="StartAndExpand" HorizontalOptions="CenterAndExpand">
<Button x:Name="btnGrid2"/>
</Grid>
</Grid>
Code-behind
private void Button1_Clicked(object sender, EventArgs e)
{
Grid2.IsVisible = false;
Grid1.IsVisible = true;
}
private void Button2_Clicked(object sender, EventArgs e)
{
Grid2.IsVisible = true;
Grid1.IsVisible = false;
}
I am currently working on a Xamarin CrossPlatform project and have implemented a Listview bound to an ObservableCollection. Everything works out fine until I remove an Item from the ListView. The images in the follow up items within the ListView disappear randomly - not all of them and a different amount of them every time. I guess it has something to do with the MemoryStream, but what do I have to change? Here´s the relevant part of my Model that is bound to the ListView:
public string ImageBase64
{
get
{
return imagebase64;
}
set
{
if (imagebase64 != value)
{
imagebase64 = value;
OnPropertyChanged(nameof(ImageBase64));
OnPropertyChanged(nameof(ImageSource));
}
}
}
public ImageSource ImageSource
{
get
{
if (!string.IsNullOrEmpty(imagebase64))
{
return ImageSource.FromStream(() => new MemoryStream(Convert.FromBase64String(imagebase64)));
}
else
{
return null;
}
}
}
Here´s the relevant XAML:
<ListView x:Name="listView" Margin="20" ItemsSource="{Binding}" ItemSelected="OnListItemSelected" HasUnevenRows="True" SeparatorColor="{StaticResource primaryGreen}" SeparatorVisibility="Default">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Margin="0,5,0,5">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="65" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="45" />
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Grid.RowSpan="3" Margin="-2,-2,-2,-2" Source="{Binding ImageSource}" HorizontalOptions="Start" VerticalOptions="Center" Aspect="AspectFill"/> <!-- This is the displayed Image -->
<Label Margin="10,0,0,0" Grid.Column="1" Grid.Row="0" FontAttributes="Bold" FontSize="18" TextColor="{StaticResource primaryGreen}" Text="{Binding VorNachname}" VerticalTextAlignment="Start" HorizontalTextAlignment="Start"/>
<Label Margin="10,0,0,0" Grid.Column="1" Grid.Row="1" Text="{Binding MediumSelected.Wert, StringFormat='via {0}'}" HorizontalOptions="FillAndExpand" VerticalTextAlignment="Start" HorizontalTextAlignment="Start"/>
<StackLayout Margin="10,0,0,0" Grid.Column="1" Grid.Row="2" Orientation="Horizontal" HorizontalOptions="FillAndExpand">
<Label Text="{Binding Alter,StringFormat='Alter: {0}'}" VerticalTextAlignment="Start" HorizontalTextAlignment="Start" HorizontalOptions="Start"/>
</StackLayout>
<StackLayout Margin="0,0,0,-5" Grid.Column="2" Grid.RowSpan="3" Orientation="Vertical" HorizontalOptions="End" VerticalOptions="End">
<Button WidthRequest="40" HeightRequest="40" BackgroundColor="White" BorderWidth="0" BorderColor="White" Image="socialmedia_18.png" Clicked="OnChangeClicked" CommandParameter ="{Binding}" VerticalOptions="EndAndExpand" />
<Button Margin="0,-15,0,0" WidthRequest="40" HeightRequest="40" BackgroundColor="White" BorderColor="White" Image="cancel_18.png" Clicked="OnDeleteClicked" CommandParameter ="{Binding}" VerticalOptions="End" />
</StackLayout>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
...and the Code behind:
async void OnDeleteClicked(object sender, EventArgs e)
{
Helper.TrackEvent("PeopleList_OnDeleteClicked");
//Get selected Person
Person person = (Person)((Button)sender).CommandParameter;
//Remove from Model
DBHelper.DBModel.People.Remove(person);
//Update database
App.Database.UpdateWithChildren(DBHelper.DBModel);
}
EDIT:
Resizing the images does not help, same problem. I tried it by binding a testvariable ImageSourceThumb to the ListViewItemImage:
public ImageSource ImageSourceThumb
{
get
{
if (!string.IsNullOrEmpty(imagebase64))
{
return ImageSource.FromStream(() => new MemoryStream(ImageResizer.ResizeImage(Convert.FromBase64String(imagebase64), 64, 64)));
}
else
{
return null;
}
}
}
I had a similar problem. When I loaded or updated my listview not all the images showed up.
I fixed my problem resizing the images. Huge images gived me a outofmemory exception. Resizing those images to a smaller resolution fixed these problems.