When change an object inside a CollectionView multiple objects are affected - xamarin.forms

If I hide an image visibility in CollectionView, multiple image visibility is affecting but image Tapped event fires once.
Simplified CollectionView xaml..
<CollectionView x:Name="favCollectionView"
ItemsSource="{Binding FavoriteCollection}"
RemainingItemsThresholdReachedCommand="{Binding GetNextDatas}"
RemainingItemsThreshold="1"
ItemSizingStrategy="MeasureAllItems"
ItemsLayout="VerticalList"
SelectionMode="Single">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid VerticalOptions="FillAndExpand">
<Label Grid.Row="0" Text="{Binding TargetText}"/>
<Image Grid.Row="0" Aspect="AspectFill" Source="seeResult.png">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="Tapped_TranslatedResult"/>
</Image.GestureRecognizers>
</Image>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
Code behind..
void Tapped_TranslatedResult(System.Object sender, System.EventArgs e)
{
var img = sender as Image;
if (img != null)
{
img.Opacity = 0;
}
}
For example, If I have 50 rows in CollectionView and tapped once top second image item, next ninth image's visibility is changed too and again next ninth one too, so on..
What could be the problem?

I changed the Image to ImageButton and then added Command parameter. The key was the Jason's comment. Binding the Model property to my ImageButton's IsVisibility property and it worked correctly.

Related

Xamarin - How to call a function in Collection View without error?

I'm trying to call a function in a Xamarin project by using the SelectionChanged property.
Inside this property, I've called a function that I've declared in the cs file.
Here is the XAML code:
<CollectionView x:Name="PCCollection" SelectionMode="Single" SelectionChanged="Cell_Tapped" AutomationId="{Binding Tipologia_Alimento}">
Here is the CS function:
private async void Cell_Tapped(object sender, System.EventArgs e) {
Console.WriteLine("Tapped");
Console.WriteLine((sender as Cell).AutomationId.ToString());
}
When I click on the Collection View cell, it prints the value "Tapped" but it gives me also the Break Mode error: "The application is in break mode".
Could you help me with this error?
Thanks in advance.
Your syntax is not valid. The Collection View control does not have AutomationId property.
Sample
<CollectionView ItemsSource="{Binding Monkeys}"
SelectionChanged="Cell_Tapped"
SelectionMode="Single">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="10">
<Label Grid.Column="1"
Text="{Binding Name}"
FontAttributes="Bold" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
void Cell_Tapped(object sender, SelectionChangedEventArgs e)
{
if (((CollectionView)sender).SelectedItem == null)
return;
string current = (e.CurrentSelection.FirstOrDefault() as Monkey)?.Name;
}
You can find more here
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/collectionview/selection
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/collectionview/populate-data

Xamarin CollectionView - Scroll Programatically

I have collection view . See below code
<CollectionView ItemsSource="{Binding photos}" HeightRequest="300"
ItemSizingStrategy="MeasureAllItems" Margin="10,0,10,0"
x:Name="photosView"
ItemsUpdatingScrollMode="KeepScrollOffset">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical" Span="3" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Padding="2">
<Frame BackgroundColor="Red" HeightRequest="79" WidthRequest="53" Padding="0" Margin="0"
IsClippedToBounds="True" HasShadow="False" CornerRadius="10">
<Image Aspect="AspectFill" Source="{Binding imageUrl}"/>
</Frame>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
I am showing 3 rows and 3 columns of the images. If I have more than 9 images then I am showing Button which says Scroll for more photos. Now On click on the imageI have below code
void OnScrollMore(System.Object sender, System.EventArgs e)
{
//photosView.SendScrolled(new ItemsViewScrolledEventArgs() { FirstVisibleItemIndex = 0 });
photosView.ScrollTo(photosView.Y + 10, position: ScrollToPosition.MakeVisible, animate: true);
}
But nothing is happening . It is not getting scrolled to next row.
Any suggestions?
The reason your ScrollTo method is not working is because the photosView can't find the item 'photosView.Y + 10' in your photosView itemssource. The method you're invoking is trying to find an item in the ItemsSource. It is not scrolling to a y-position like you're trying to do. You can see it in the description of the method when going to the definition. It is waiting for an 'object item'.
public void ScrollTo(object item, object group = null, ScrollToPosition position = ScrollToPosition.MakeVisible, bool animate = true);
If what you're trying to do is scroll to the last added item of the collectionview, then try this working approach and build it up from there. Here everytime you press the button, an item (string) gets added. This item is set as the ScrollTo object at the end of the button click handler.
MainPage.xaml
<StackLayout Orientation="Vertical">
<CollectionView ItemsSource="{Binding photos}" HeightRequest="300"
ItemSizingStrategy="MeasureAllItems" Margin="10,0,10,0"
x:Name="photosView"
ItemsUpdatingScrollMode="KeepLastItemInView">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical" Span="3" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Padding="2">
<Frame BackgroundColor="Red" HeightRequest="79" WidthRequest="53" Padding="0" Margin="0"
IsClippedToBounds="True" HasShadow="False" CornerRadius="10">
<Label Text="{Binding}" TextColor="White"
HorizontalOptions="Center" VerticalOptions="Center"
HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/>
</Frame>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<Button Text="scroll more" HorizontalOptions="Center" VerticalOptions="End" Clicked="OnScrollMore"/>
</StackLayout>
MainPage.xaml.cs
public partial class MainPage : ContentPage
{
ObservableCollection<string> ObservableItems { get; set; }
public MainPage()
{
InitializeComponent();
ObservableItems = new ObservableCollection<string>(new List<string>() { "een", "twee", "drie" });
photosView.ItemsSource = ObservableItems;
}
void OnScrollMore(System.Object sender, System.EventArgs e)
{
var item = (ObservableItems.Count + 1).ToString();
ObservableItems.Add(item);
photosView.ScrollTo(item, position: ScrollToPosition.MakeVisible, animate: true);
}
}
Resulting in:

Change all xamarin forms button background inside a listview

I have ListView with buttons inside.When button is clicked I need some way to change the background color of all other buttons exept the clicked button.
Initially all buttons inside my listview have a white background, when a button is clicked i check is background color is white then change to gray color and need to change background colors to white for all other buttons.
This is the code:
<control:ListViewNestedScroll
x:Name="ClassLevelListView"
HasUnevenRows="True"
RowHeight="30"
SeparatorVisibility="None"
IsPullToRefreshEnabled="True"
IsRefreshing="{Binding IsRunning, Mode=TwoWay}"
RefreshCommand="{Binding LoadClassLevelsCommand}"
ItemsSource="{Binding ClassLevels}">
<ListView.ItemTemplate>
<DataTemplate>
<control:CustomViewCell SelectedBackgroundColor="{StaticResource GreyColor}">
<StackLayout Margin="0,0,0,10">
<control:CustomButton
Text="{Binding KeyName, Converter={StaticResource I18N}}"
CornerRadius="20"
BorderColor="Black"
BorderWidth="2"
TextColor="Black"
BackgroundColor="White"
CommandParameter="{Binding .}"
Clicked="Button_OnClicked" />
</StackLayout>
</control:CustomViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</control:ListViewNestedScroll>
private void Button_OnClicked(object sender, EventArgs e)
{
var classLevelButton = (Button)sender;
var classLevel = classLevelButton.CommandParameter as ClassLevelModel;
if (classLevelButton.BackgroundColor == Color.White)
{
classLevelButton.BackgroundColor = (Color)Application.Current.Resources["GreyColor"];
((RegisterTeacherClassLevelViewModel)BindingContext).AddTeacherClassLevel(classLevel);
}
else
{
classLevelButton.BackgroundColor = Color.White;
((RegisterTeacherClassLevelViewModel)BindingContext).RemoveTeacherClassLevel(classLevel);
}
}

Xamarin : Change label text inside listview

I am new with xamarin, I am facing an issue in my xamarin forms project.
I have a Label and 2 images inside listview-viewcell. I want to change the label text onclick of images. Increase the label text value by 1 if click like and decrease by 1 if click unlike. I use the label x:name, but it is not accessible in class. How can i fix this?
<StackLayout>
<ListView>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<Label
Text="{Binding likeCount}"
x:Name="likecount"/>
<Image Source="like.png">
<Image.GestureRecognizers>
<TapGestureRecognizer
Tapped="LikeOrUnlikeTweet"
CommandParameter="{Binding .}"
NumberOfTapsRequired="1" />
</Image.GestureRecognizers>
</Image
<Image Source="unlike.png">
<Image.GestureRecognizers>
<TapGestureRecognizer
Tapped="LikeOrUnlikeTweet"
CommandParameter="{Binding .}"
NumberOfTapsRequired="1" />
</Image.GestureRecognizers>
</Image
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
Anybody please suggest a solution with working code.
Thanks in advance
First of you need to create command in your VM and need to change as follow:
<TapGestureRecognizer
Tapped="{Binding Source={x:Reference YourListName}, Path=BindingContext.LikeOrUnlikeTweetCommand}"
CommandParameter="{Binding .}"
NumberOfTapsRequired="1" />
ViewModel Code
public ICommand LikeOrUnlikeTweetCommand { get; }
Initialise in constructor
LikeOrUnlikeTweetCommand = new Command<YourModelDto>(LikeOrUnlikeTweet);
Function code in this you change your count value and update list.
void LikeOrUnlikeTweet(YourModelDto yourModelDto)
{
....
}
I would take one of 2 paths for doing this:
Use an ObservableCollection as ItemsSource for your list, obvious when you change properties of an item they would be reflected in the list. What the list view would do is it would replace the old item with the new one modified with your new values. You can make a search about what an ObservableCollection collection is.
My actual way, as im fighting low performance of android with listviews, and this makes it: you can create a custom class for ViewCell, avoid low-speed bindings, set all properties inside your custom ViewCell by code. When the cell bindigcontext changes more likely the ItemsSource item is being assigned to your cell, so you can now take its value ans set it up.
protected override void OnBindingContextChanged()
{
SetupCell(); //assign values to named controls manually
base.OnBindingContextChanged();
}
public void SetupCell()
{
var item = BindingContext as YouItemClass;
if (item == null) return;
txtTitle.Text = item.Name;
//etc
...

WP7 Updating Pivot control title

I have a Pivot control which I am using as following within the XAML.
I have bound the Pivot Title to a method on my view model as its content will vary depending upon what is being displayed.
<controls:Pivot x:Name="MainPivot" ItemsSource="{Binding PivotItemHeaders}" Title="{Binding ApplicationTitle}" >
<controls:Pivot.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Description}"/>
</DataTemplate>
</controls:Pivot.HeaderTemplate>
<controls:Pivot.ItemTemplate>
<DataTemplate>
<ListBox x:Name="EventsListbox"
ItemsSource="{Binding allEventItems}"
ItemTemplate="{StaticResource EventDisplay3}"
SelectionChanged="EventsListbox_SelectionChanged"/>
</DataTemplate>
</controls:Pivot.ItemTemplate>
</controls:Pivot>
The collection of items is being refreshed and the binding is working fine for these objects - however the Pivot title is not refreshing with the new value.
It seems stuck at the value when the page/pivot control was first shown.
Any ideas how I can get the pivot control to refresh? - Thanks
I just did a quick test, binding works just fine:
<controls:Pivot Title="MY APPLICATION" ItemsSource="{Binding Items}">
<controls:Pivot.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding LineOne}" />
</DataTemplate>
</controls:Pivot.HeaderTemplate>
<controls:Pivot.ItemTemplate>
<DataTemplate>
<Grid>
<Button Content="Update" Click="Button_Click" />
</Grid>
</DataTemplate>
</controls:Pivot.ItemTemplate>
</controls:Pivot>
And in the C#
private void Button_Click(object sender, RoutedEventArgs e)
{
App.ViewModel.Items.Clear();
App.ViewModel.Items.Add(new ItemViewModel() { LineOne = "foo" });
App.ViewModel.Items.Add(new ItemViewModel() { LineOne = "bar" });
App.ViewModel.Items.Add(new ItemViewModel() { LineOne = "baz" });
}
So clearly you're doing something very wrong. Post your code and we'll take a look.
Update
Title Binding also works
XAML
<controls:Pivot Title="{Binding Title}">
<controls:PivotItem Header="first">
<Grid>
<Button Click="Button_Click" Content="OK!" />
</Grid>
</controls:PivotItem>
</controls:Pivot>
C#:
private void Button_Click(object sender, RoutedEventArgs e)
{
Title = "foobar!";
PropertyChanged(this, new PropertyChangedEventArgs("Title"));
}

Resources