I'm trying to Sticky x:Name="_menucate" when scrolling like the example on Twitter
[![enter image description here][1]][1]
[![enter image description here][2]][2]
<ScrollView x:Name="scrollmain" Scrolled="scrollmain_Scrolled" VerticalScrollBarVisibility="Never" HorizontalScrollBarVisibility="Never" Margin="0,0,0,0">
<StackLayout>
<StackLayout>
<Frame/>
<Frame/>
<Frame/>
<Frame/>
</StackLayout>
<StackLayout>
<ScrollView x:Name="_menucate" Orientation="Horizontal" VerticalScrollBarVisibility="Never" HorizontalScrollBarVisibility="Never">
<Grid Margin="0" Padding="5,0" HorizontalOptions="FillAndExpand" VerticalOptions="CenterAndExpand" ColumnSpacing="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Row="0" Grid.Column="0" HorizontalOptions="FillAndExpand">
<Label Text="Menu 1" />
</Grid>
<Grid Grid.Row="0" Grid.Column="1" HorizontalOptions="FillAndExpand">
<Label Text="Menu 2" />
</Grid>
</Grid>
</ScrollView>
<StackLayout>
<Frame/>
<Frame/>
</StackLayout>
</StackLayout>
</StackLayout>
</ScrollView>
Page1.xaml.cs
public Page1()
{
scrollmain.PropertyChanged += Scrollmain_PropertyChanged;
_menucate.SizeChanged += _menucate_SizeChanged;
}
double _titleTextTop;
private void _menucate_SizeChanged(object sender, EventArgs e)
{
_menucate.SizeChanged -= _menucate_SizeChanged;
_titleTextTop = _menucate.Y;
}
private void Scrollmain_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName.Equals(Xamarin.Forms.ScrollView.ScrollYProperty.PropertyName))
{
var scrolled = ((Xamarin.Forms.ScrollView)sender).ScrollY;
if (scrolled < _titleTextTop)
_menucate.TranslationY = (0 - scrolled);
else
_menucate.TranslationY = (0 - _titleTextTop);
}
}
private void scrollmain_Scrolled(object sender, ScrolledEventArgs e)
{
//Load more other
}
I have tried to do as the code above. However it doesn't work. Maybe I misunderstood the problem. Looking forward to everyone's help. Thank you
Update 1 .xaml
I removed 1 ScrollView inside ScrollView x:Name="scrollmain"
<ScrollView x:Name="scrollmain" Scrolled="scrollmain_Scrolled">
<StackLayout>
<StackLayout>
<Frame/>
...... //more
</StackLayout>
<StackLayout>
<Grid x:Name="_menucate" Margin="0" Padding="5,0" ColumnSpacing="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Row="0" Grid.Column="0">
<Label Text="Menu 1" />
</Grid>
<Grid Grid.Row="0" Grid.Column="1">
<Label Text="Menu 2" />
</Grid>
</Grid>
<StackLayout>
.... //More
</StackLayout>
</StackLayout>
</StackLayout>
</ScrollView>
Update 2
<Grid RowSpacing="0" ColumnSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid x:Name="ContentGrid" RowSpacing="0" ColumnSpacing="0" Grid.Row="0">
<Label Text="FIXED HEADER DEMO" Margin="12" FontSize="14" />
<ScrollView x:Name="TheScroll">
<StackLayout>
<StackLayout x:Name="BearImage">
<Image Source="https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__480.jpg"
Aspect="AspectFill"/>
<Image Source="https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__480.jpg"
Aspect="AspectFill"/>
<Image Source="https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__480.jpg"
Aspect="AspectFill"/>
<Image Source="https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__480.jpg"
Aspect="AspectFill"/>
<Image Source="https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__480.jpg"
Aspect="AspectFill"/>
<Image Source="https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__480.jpg"
Aspect="AspectFill"/>
</StackLayout>
<Label LineBreakMode="WordWrap"
Margin="12,5,12,5"
Grid.Row="1">
<Label.FormattedText>
<FormattedString>
<Span Text="Never heard before, but a bear was found in the wild!" FontAttributes="Bold" FontSize="18" />
<Span Text="
Bears are mammals of the family Ursidae. Bears are classified as caniforms, or doglike carnivorans, with the pinnipeds being their closest living relatives. Although only eight species of bears are extant, they are widespread, appearing in a wide variety of habitats throughout the Northern Hemisphere and partially in the Southern Hemisphere. Bears are found on the continents of North America, Central America, South America, Europe, and Asia.
Common characteristics of modern bears include large bodies with stocky legs, long snouts, shaggy hair, plantigrade paws with five nonretractile claws, and short tails. While the polar bear is mostly carnivorous and the giant panda feeds almost entirely on bamboo, the remaining six species are omnivorous, with varied diets.
With the exceptions of courting individuals and mothers with their young, bears are typically solitary animals. They are generally diurnal, but may be active during the night (nocturnal) or twilight (crepuscular), particularly around humans. Bears are aided by an excellent sense of smell, and despite their heavy build and awkward gait, they can run quickly and are adept climbers and swimmers. In autumn, some bear species forage large amounts of fermented fruits, which affects their behaviour.[1] Bears use shelters, such as caves and burrows, as their dens; most species occupy their dens during the winter for a long period (up to 100 days) of sleep similar to hibernation.[2]
FontSize="14" />
</FormattedString>
</Label.FormattedText>
</Label>
</StackLayout>
</ScrollView>
<ScrollView x:Name="_menucate" Orientation="Horizontal" HeightRequest="40" VerticalOptions="Start">
<StackLayout Orientation="Horizontal" Spacing="-6" Padding="1">
<Button Text="Menu1" />
<Button Text="Menu2" />
<Button Text="Menu3" />
<Button Text="Menu4" />
<Button Text="Menu5" />
<Button Text="Menu6" />
<Button Text="Menu7" />
<Button Text="Menu8" />
</StackLayout>
</ScrollView>
</Grid>
</Grid>
.xaml.cs
double _titleTextTop;
public Page1()
{
InitializeComponent();
TheScroll.PropertyChanged += OnScrollViewPropertyChanged;
BearImage.SizeChanged += OnBearImageSizeChanged;
_menucate.SizeChanged += OnTitleTextSizeChanged;
}
private void OnTitleTextSizeChanged(object sender, System.EventArgs e)
{
_menucate.SizeChanged -= OnTitleTextSizeChanged;
//As soon as the news header has been repositioned, we can grab the actual screen top position
_titleTextTop = _menucate.Y;
//Remark: GetScreenCoordinates will get the actual position on screen instead of the actual position inside the parent
//_titleTextTop = GetScreenCoordinates(TitleText).Y;
}
private void OnBearImageSizeChanged(object sender, System.EventArgs e)
{
BearImage.SizeChanged -= OnBearImageSizeChanged;
//When the bear image has been loaded, reposition the news header to the bottom of this image
_menucate.Margin = new Thickness(0, BearImage.Height - 40, 0, 0);
}
private void OnScrollViewPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName.Equals(ScrollView.ScrollYProperty.PropertyName))
{
var scrolled = ((ScrollView)sender).ScrollY;
System.Diagnostics.Debug.WriteLine($"Y position: {scrolled.ToString()}");
if (scrolled < _titleTextTop)
_menucate.TranslationY = (0 - scrolled);
else
_menucate.TranslationY = (0 - _titleTextTop);
}
}
public (double X, double Y) GetScreenCoordinates(VisualElement view)
{
// A view's default X- and Y-coordinates are LOCAL with respect to the boundaries of its parent,
// and NOT with respect to the screen. This method calculates the SCREEN coordinates of a view.
// The coordinates returned refer to the top left corner of the view.
// Initialize with the view's "local" coordinates with respect to its parent
double screenCoordinateX = view.X;
double screenCoordinateY = view.Y;
// Get the view's parent (if it has one...)
if (view.Parent.GetType() != typeof(App))
{
VisualElement parent = (VisualElement)view.Parent;
// Loop through all parents
while (parent != null)
{
// Add in the coordinates of the parent with respect to ITS parent
screenCoordinateX += parent.X;
screenCoordinateY += parent.Y;
// If the parent of this parent isn't the app itself, get the parent's parent.
if (parent.Parent.GetType() == typeof(App))
parent = null;
else
parent = (VisualElement)parent.Parent;
}
}
// Return the final coordinates...which are the global SCREEN coordinates of the view
return (screenCoordinateX, screenCoordinateY);
}
It seems that when the data inside the <StackLayout x:Name="BearImage"> exceeds the current screen, the x:Name="_menucate" is no longer visible. As in the example above I leave 5 images -> do not exceed the screen, then it displays x:Name="_menucate", if the number of images is greater than 5 -> passes the current screen, then x:Name="_menucate" won't show up?
All you have to do is to update the _menucate's TranslationY while scrolling the page!
Here's the code sample for your reference:
Code in Xaml:
<Grid RowSpacing="0" ColumnSpacing="0">
<Grid.Margin>
<OnPlatform x:TypeArguments="Thickness">
<On Platform="iOS" Value="0,20,0,0" />
</OnPlatform>
</Grid.Margin>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Text="FIXED HEADER DEMO" Margin="12" Grid.Row="0" FontSize="14" />
<Grid x:Name="ContentGrid" RowSpacing="0" ColumnSpacing="0" Grid.Row="1">
<ScrollView x:Name="TheScroll">
<Grid RowSpacing="0" ColumnSpacing="0">
<Grid.RowDefinitions>
<RowDefinition x:Name="ImageRow" Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Image x:Name="BearImage" Source="XamarinLogo.png"
Aspect="AspectFill"
Grid.Row="0" />
<Label LineBreakMode="WordWrap"
Margin="12,5,12,5"
Grid.Row="1">
<Label.FormattedText>
<FormattedString>
<Span Text="Never heard before, but a bear was found in the wild!" FontAttributes="Bold" FontSize="18" />
<Span Text="
Bears are mammals of the family Ursidae. Bears are classified as caniforms, or doglike carnivorans, with the pinnipeds being their closest living relatives. Although only eight species of bears are extant, they are widespread, appearing in a wide variety of habitats throughout the Northern Hemisphere and partially in the Southern Hemisphere. Bears are found on the continents of North America, Central America, South America, Europe, and Asia.
Common characteristics of modern bears include large bodies with stocky legs, long snouts, shaggy hair, plantigrade paws with five nonretractile claws, and short tails. While the polar bear is mostly carnivorous and the giant panda feeds almost entirely on bamboo, the remaining six species are omnivorous, with varied diets.
With the exceptions of courting individuals and mothers with their young, bears are typically solitary animals. They are generally diurnal, but may be active during the night (nocturnal) or twilight (crepuscular), particularly around humans. Bears are aided by an excellent sense of smell, and despite their heavy build and awkward gait, they can run quickly and are adept climbers and swimmers. In autumn, some bear species forage large amounts of fermented fruits, which affects their behaviour.[1] Bears use shelters, such as caves and burrows, as their dens; most species occupy their dens during the winter for a long period (up to 100 days) of sleep similar to hibernation.[2]
Bears have been hunted since prehistoric times for their meat and fur. With their tremendous physical presence and charisma, they play a prominent role in the arts, mythology, and other cultural aspects of various human societies. In modern times, the bears' existence has been pressured through the encroachment on their habitats and the illegal trade of bears and bear parts, including the Asian bile bear market. The IUCN lists six bear species as vulnerable or endangered, and even least concern species, such as the brown bear, are at risk of extirpation in certain countries. The poaching and international trade of these most threatened populations are prohibited, but still ongoing."
FontSize="14" />
</FormattedString>
</Label.FormattedText>
</Label>
</Grid>
</ScrollView>
<ScrollView x:Name="_menucate" Orientation="Horizontal" HeightRequest="40" VerticalOptions="Start">
<StackLayout Orientation="Horizontal" Spacing="-6" Padding="1">
<Button Text="Menu1" />
<Button Text="Menu2" />
<Button Text="Menu3" />
<Button Text="Menu4" />
<Button Text="Menu5" />
<Button Text="Menu6" />
<Button Text="Menu7" />
<Button Text="Menu8" />
</StackLayout>
</ScrollView>
</Grid>
</Grid>
Code behind:
public partial class Page1 : ContentPage
{
double _titleTextTop;
public Page1()
{
InitializeComponent();
TheScroll.PropertyChanged += OnScrollViewPropertyChanged;
BearImage.SizeChanged += OnBearImageSizeChanged;
_menucate.SizeChanged += OnTitleTextSizeChanged;
}
private void OnTitleTextSizeChanged(object sender, System.EventArgs e)
{
_menucate.SizeChanged -= OnTitleTextSizeChanged;
//As soon as the news header has been repositioned, we can grab the actual screen top position
_titleTextTop = _menucate.Y;
//Remark: GetScreenCoordinates will get the actual position on screen instead of the actual position inside the parent
//_titleTextTop = GetScreenCoordinates(TitleText).Y;
}
private void OnBearImageSizeChanged(object sender, System.EventArgs e)
{
BearImage.SizeChanged -= OnBearImageSizeChanged;
//When the bear image has been loaded, reposition the news header to the bottom of this image
_menucate.Margin = new Thickness(0, BearImage.Height - 40, 0, 0);
}
private void OnScrollViewPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName.Equals(ScrollView.ScrollYProperty.PropertyName))
{
var scrolled = ((ScrollView)sender).ScrollY;
System.Diagnostics.Debug.WriteLine($"Y position: {scrolled.ToString()}");
if (scrolled < _titleTextTop)
//you can set the position by setting below
_menucate.TranslationY = (0 - scrolled);
else
_menucate.TranslationY = (0 - _titleTextTop);
}
}
}
Related
I'm wondering how we can achieve in Xamarin Forms a title transition in nav bar when user scrolling. For example, the Message app on iOS :
When user scroll :
Title "Messages" transition from page content to navigation bar. Is there a way to accomplish this in the same way on Android and iOS with Xamarin Forms ?
We could define a custom TitleView and set the TextColor of title when scrolling the page .
in Xaml
<NavigationPage.TitleView>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.2*" />
<ColumnDefinition Width="0.6*" />
<ColumnDefinition Width="0.2*" />
</Grid.ColumnDefinitions>
<Label x:Name="TitleLabel" Text="Message" FontSize="22" TextColor="Transparent" Grid.Column="1" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" />
//... you can put any other elements on other two Columns like button and image icon
</Grid>
</NavigationPage.TitleView>
For content I defined a simple ScrollView for show the effect
<ScrollView Scrolled="ScrollView_Scrolled" Orientation="Vertical">
<StackLayout>
<Label Text="Message" FontSize="35" HorizontalTextAlignment="Start" HeightRequest="60" />
<BoxView BackgroundColor="LightBlue" HeightRequest="300" />
<BoxView BackgroundColor="LightGreen" HeightRequest="300" />
<BoxView BackgroundColor="LightPink" HeightRequest="300" />
</StackLayout>
</ScrollView>
In code behind
Note :
60 here is the height of label in content Page . The alpha of title Label will set to 1 when the message label scrolls out of the screen. I didn't used data binding just for demo . Of course you could binding the TextColor to ViewModel .
private void ScrollView_Scrolled(object sender, ScrolledEventArgs e)
{
var scrollView = sender as ScrollView;
var TransY = e.ScrollY;
if(TransY>0)
{
double alpha = TransY / 60;
TitleLabel.TextColor = Color.FromRgba(0.0,0.0,0.0,alpha);
}
}
Im facing a real strange problem, I am developing a xamarin forms app, let me show you the problem:
So I have this listview with items.
click here to see the list
Then i tapped an item, and this fires a Navigation.PushAsync to this page
Then, when i go back to the list, The image size has changed, watch this image
I have tried change the list view to a collection view but the problem is the same. Im deploying this app on android
This is the xaml code
<StackLayout Margin="10,0,10,0">
<ListView x:Name="lvResultadoBusqueda" SelectionMode="Single" ItemSelected="lvResultadoBusqueda_ItemSelected" ItemTapped="lvResultadoBusqueda_ItemTapped" HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" BackgroundColor="#FFFFFF" Padding="0,5,0,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="15"/>
<RowDefinition Height="15"/>
<RowDefinition Height="15"/>
<RowDefinition Height="10"/>
</Grid.RowDefinitions>
<Frame Padding="0" OutlineColor="#E4E7EC" HasShadow="True" Grid.RowSpan="4" Grid.Column="0">
<Image Source="{Binding urlImagenPortada}" Aspect="Fill"></Image>
</Frame>
<Label Text="{Binding titulo}" Grid.Row="0" Grid.Column="1" FontSize="14" TextColor="#000000" FontAttributes="Bold"></Label>
<Label Text="{Binding autores}" FontSize="12" Grid.Row="1" Grid.Column="1" TextColor="#868b8f"></Label>
<StackLayout Grid.Row="2" Grid.Column="1" Orientation="Horizontal" Spacing="5" BackgroundColor="Transparent">
<Label Text="{Binding valoracionExacta}" FontSize="12" TextColor="#868b8f" BackgroundColor="Transparent"></Label>
<Image Source="star_blue.png" WidthRequest="10" HeightRequest="10" Margin="0,4,0,0"></Image>
</StackLayout>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
and this is the c# code
private void lvResultadoBusqueda_ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
ListView listView = (ListView)sender;
listView.SelectedItem = null;
}
private void lvResultadoBusqueda_ItemTapped(object sender, ItemTappedEventArgs e)
{
var item = e.Item as BuscarCatalogoVM;
if (item != null)
{
Navigation.PushAsync(new Catalogo.DetalleCatalogo(item.idRepositorioDigital));
}
}
I really hope you can help me, thanks !
UPDATE 1: I tried what Ryan told me:
<Frame Padding="0" OutlineColor="#E4E7EC" HasShadow="True" Grid.RowSpan="4" Grid.Column="0">
<Image Source="{Binding urlImagenPortada}" Aspect="AspectFit" HorizontalOptions="FillAndExpand"></Image>
</Frame>
And this is the screenshot :C
UPDATE 2: With the FFImageLoading plugin, I dont have that problem, it works great, but it seems that the DownsampleToViewSize property is not working, when I set it to true, the image does not fit , So I have to put it false and add Aspect="Fill" or Aspect="AspectFill", but this solutions cuts the image of the book
Friend from Peru
Try using Xamarin.FFImageLoading.Forms
https://askxammy.com/optimizing-handling-images-with-ffimageloading/
Also
I share this link for the management of transitions.
https://geeks.ms/jsuarez/2019/05/29/xamarin-forms-ui-challenge-art-news-transiciones-entre-paginas/
You can share the code in git and I'm debugging the project to try to help you.
<Frame Padding="0" OutlineColor="#E4E7EC" HasShadow="True" Grid.RowSpan="4" Grid.Column="0">
<Image Source="{Binding urlImagenPortada}" Aspect="AspectFill" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"></Image>
</Frame>
add HorizontalOptions="FillAndExpand" and VerticalOptions="FillAndExpand"
I need to integrate the Dynamic horizontal listview in my project. I found this concept below blog on the website. But I confused this code to integrate into my project. Kindly suggest me an idea to anyone. I need this image type grid or horizontal listview( https://i.stack.imgur.com/OvJZE.png).
Mainpage.xaml.cs
public void SetupUserStack()
{
---------- issue in _itemSelectCommand in my code
cButtonList.Add(new CircleButton(_itemSelectCommand)
{ CircleSize = otherCircleSize, CircleFontSize = 35, Text = initials, BackgroundColor = Color.White, TextColor = ourBlue, BorderColor = ourBlue, BorderWidth = 1.5 });
var b2 = new Button() { Text = lname, TextColor = ourBlue };
//otherGrid.Children.Add(LargeCB, 0, 0);
otherGrid.Children.Add(cButtonList[i], 0, 0);
otherGrid.Children.Add(b2, 0, 1);
UserStack.Children.Add(otherGrid);
}
Blog I refer: horizontal-list-view-with-circular-button-styling-in-xamarin-forms
This is the another way to achieve the same thing. Xamarin forms now support the Bindable Layouts
XAML Code:
<ScrollView
Orientation="Horizontal"
HorizontalScrollBarVisibility="Default">
<StackLayout Margin="20,0,20,0"
Orientation="Horizontal"
BindableLayout.ItemsSource="{Binding LogoImages}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Image
HeightRequest="25"
Margin="0,0,5,0"
Source="{Binding logoImage}">
</Image>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</ScrollView>
Here is more information with the example :
Bindable Layouts
Use a collectionView to create a horizontal-list would be easier and faster, for example:
<CollectionView ItemsSource="{Binding Monkeys}"
ItemsLayout="HorizontalList">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="35" />
<RowDefinition Height="35" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70" />
<ColumnDefinition Width="140" />
</Grid.ColumnDefinitions>
<Image Grid.RowSpan="2"
Source="{Binding ImageUrl}"
Aspect="AspectFill"
HeightRequest="60"
WidthRequest="60" />
<Label Grid.Column="1"
Text="{Binding Name}"
FontAttributes="Bold"
LineBreakMode="TailTruncation" />
//...your layout
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
The Monkeys should be a list that in your ViewModel.
You can check the sample with MVVM structure here:collectionviewdemos
In your linking blog, he creates the grid dynamically with the users.Count and I think it hard to integrate his code to MVVM structure.
Git: https://github.com/jimmyt1988/Test
I'm running on desktop windows 10 pc on UWP Local device "emulator"
I have a deep integer property in my view model that gets incremented by a button command.
When i do, the number disapears from the screen, and then if i resize my application, it will render correctly again.
What's happening?
It seems to work on the Android emulator.
Code
public DelegateCommand<FoodGroupModel> SubtractFromAmountEatenCommand { get; private set; }
...
SubtractFromAmountEatenCommand = new DelegateCommand<FoodGroupModel>((foodGroup) => SubtractFromAmountEaten(foodGroup));
...
public void SubtractFromAmountEaten(FoodGroupModel foodGroup)
{
if(foodGroup.AmountEaten != 0)
{
foodGroup.AmountEaten--;
}
}
...
public class FoodGroupModel : BindableBase
{
private int _amountEaten;
public int AmountEaten
{
get { return _amountEaten; }
set { SetProperty(ref _amountEaten, value); }
}
}
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:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
prism:ViewModelLocator.AutowireViewModel="True"
x:Class="...Views.MealPage">
<StackLayout>
<Label Text="{Binding Meal.Number}"/>
<ListView x:Name="FoodGroupsListView" ItemsSource="{Binding Meal.FoodGroups}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="50" />
<ColumnDefinition Width="50" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" TextColor="#bababa" Text="Group"></Label>
<Label Grid.Row="0" Grid.Column="1" Text="{Binding Title}" />
<Label Grid.Row="0" Grid.Column="2" TextColor="#bababa" Text="Qty"></Label>
<Label Grid.Row="0" Grid.Column="3" Text="{Binding AmountEaten}" />
<Button Grid.Row="0" Grid.Column="4"
Command="{Binding Source={x:Reference FoodGroupsListView}, Path=BindingContext.UndoAmountEatenByOneCommand}"
CommandParameter="{Binding}"
Text="✖"></Button>
<Button Grid.Row="0" Grid.Column="5"
Command="{Binding Source={x:Reference FoodGroupsListView}, Path=BindingContext.SubtractFromAmountEatenCommand}"
CommandParameter="{Binding}"
Text="✔"></Button>
</Grid>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
When i do, the number disapears from the screen, and then if i resize my application, it will render correctly again.
You might run into an issue: The changed notification of property binding won't work well(May be related to rerender) inside Xamarin ListView, Please report it in here: Bugzilla
In Windows runtime platform(Win/WP 8.1 & UWP), we have to use a workaround to temporarily avoid this:
private void RefreashFoodGroupModel()
{
if (Device.OS == TargetPlatform.Windows || Device.OS == TargetPlatform.WinPhone)
{
//var index = Meal.FoodGroups.IndexOf(foodGroup);
//Meal.FoodGroups.RemoveAt(index);
//Meal.FoodGroups.Insert(index, foodGroup);
var t = Meal.FoodGroups;
Meal.FoodGroups = new System.Collections.ObjectModel.ObservableCollection<FoodGroupModel>();
foreach (var item in t)
{
Meal.FoodGroups.Add(item);
}
}
}
Call the above method to refresh data after data change:
public void SubtractFromAmountEaten(FoodGroupModel foodGroup)
{
if(foodGroup.AmountEaten != 0)
{
foodGroup.AmountEaten--;
RefreashFoodGroupModel();
}
}
public void UndoAmountEatenByOne(FoodGroupModel foodGroup)
{
if (foodGroup.AmountEaten != foodGroup.Quantity)
{
foodGroup.AmountEaten++;
RefreashFoodGroupModel();
}
}
This workaround will cause the refresh of ListView items.
I have a simple ListView bound to a BindableCollection (async ObservableCollection). I am populating the BindableCollection in an async method. After a refresh, the collection contains about 130 unique items. However, the ListView displays many of the items repeatedly. Checking the actual contents of the collection, I can see they are definitely unique. The contents are something like the following
mazzy star
neil young
the babies
haunted leather
alice boman
compilations
richard swift
rolling stones
fleetwood mac
future islands
lily & madeleine
darlenya
darlenya (different from last)
father john misty
eels
sharon van etten
feeding people
helado negro
neil young first repeat
the babies
haunted leather
alice boman
compilations
richard swift
rolling stones
fleetwood mac
future islands
lily & madeleine
darlenya
darlenya (different from last)
father john misty
eels
sharon van etten
feeding people
helado negro
neil young second repeat
the babies
...
eels
The ViewModel
private readonly BindableCollection<Track> _tracks = new BindableCollection<Track>();
private readonly ITrackFeedService _feedService;
public ICollection<Track> Tracks
{
get { return _tracks; }
}
public async void UpdateTracksAsync()
{
IsBusy = true;
_tracks.Clear();
var tracks = await _feedService.LoadAsync();
_tracks.AddRange(tracks);
IsBusy = false;
}
The View (bound through caliburn.micro convention)
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ListView Name="Tracks"
ItemTemplate="{StaticResource TrackDataTemplate}"
Grid.Row="1">
</ListView>
</Grid>
<DataTemplate x:Key="TrackDataTemplate">
<Grid cm:Bind.Model="{Binding}" Margin="0 0 0 5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="10" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Name="Artwork" Height="100" Width="100"/>
<Grid Grid.Column="2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Name="Title" Style="{StaticResource TrackTextStyle}" />
<TextBlock Name="Artist" Grid.Row="1" Style="{StaticResource TrackTextStyle}" />
<TextBlock Name="Album" Grid.Row="2" />
<TextBlock Name="ReleaseYear" Grid.Row="3" />
<TextBlock Name="Label" Grid.Row="4" />
</Grid>
</Grid>
</DataTemplate>
Feed Service
public Task<IEnumerable<Track>> LoadAsync()
{
var scraper = new TrackWebScraper(URL);
return scraper.Scrape();
}
I've tried replacing BindableCollection with the standard ObservableCollection with the same result. I'm certain my service is returning a collection of unique items. I can see the ListView clearing when the collection is cleared before grabbing the new items. What am I missing?
Try this
_tracks = null;
var tracks = await _feedService.LoadAsync();
_tracks = tracks;