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

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

Related

When change an object inside a CollectionView multiple objects are affected

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.

Printing data in listview to firebase

I asked this before but no one could answer. Thanks in advance to the person who can help.
<Grid>
<ListView x:Name="lstOrder">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label Text="{Binding OrderName}" Grid.Row="0" Grid.Column="0" HorizontalTextAlignment="Start" x:Name="lblName"/>
<Label Text="{Binding OrderCount}" Grid.Row="0" Grid.Column="1" HorizontalTextAlignment="Start" x:Name="lblStepperValue"/>
<Label Text="{Binding OrderDetail}" Grid.Row="1" Grid.Column="0" HorizontalTextAlignment="Start" x:Name="edtDetail"/>
<Label Text="{Binding OrderPrice}" Grid.Row="1" Grid.Column="1" HorizontalTextAlignment="Start" x:Name="lblPriceNormal"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button BackgroundColor="Red" VerticalOptions="End" Text="Sipariş ver" x:Name="giveOrder" Clicked="giveOrder_Clicked"/>
</Grid>
This way I have a simple list view. And data is sent from realmDB to this list view. I want to send the data sent from RealmDB to this list view to my Firebase database when the button is clicked.
I don't want to write data to listview via firebase.
What I want to do is print the data in listview to firebase.
This is like printing the text on a label to firebase. I want to print the data from listview to firebase.
This is my button's code block. So when I press this button, the data in listview will be written to firebase.
that is, it will send the data on the labels to firebase.
private async void giveOrder_Clicked(object sender, System.EventArgs e)
{
await firebaseHelper.AddDoner(lstOrder.**!I can't do this part!**);
}
Hopefully it's revealing enough.
Thanks :)
This is the part I wrote for firebase, I wonder if there could be a mistake here?
public class FirebaseHelper
{
readonly FirebaseClient firebase = new FirebaseClient("my firebase link");
public async Task<List<DonerModel>> GetAllDoners()
{
return (await firebase
.Child("Doners")
.OnceAsync<DonerModel>()).Select(item => new DonerModel
{
OrderList = item.Object.OrderList
}).ToList();
}
public async Task AddDoner( string lstOrder)
{
await firebase
.Child("Doners")
.PostAsync(new DonerModel() { OrderList = lstOrder});
}
}
enter image description here
To get the list of objects that have been bound to the ListView you can use the ItemSource property.
Another point to note is that if you need the exact type (Order in your example) you can do something like this
private async void giveOrder_Clicked(object sender, System.EventArgs e)
{
if(lstOrder.ItemsSource != null && lstOrder.ItemsSource is List<OrderRealm> orders)
{
//send orders to firebase
foreach(var order in orders)
{
await firebaseHelper.AddDoner(order.*field you want to add to firebase*);
}
}
}

BindingMode=TwoWay in codebehind

Edit: apologies for the bad title, apparently something like "Setting bindingmode in code behind" didn't fit the highly nebulous requirements of SO. A title that is clearly more obvious than what the current one is.
Original: I am trying to set the binding of my listview in the code behind of its data selector template. The reason i am doing this, as I suspect (because doing something similar to it in a different template selector fixed it) that once you exit that page android seems to still contain a reference to it and then throws a amarin.forms.platform.android.viewcellrendererA disposed object exception.
my current xaml looks as follows:
<StackLayout Orientation="Vertical"
Padding="0, 20, 0, 0"
HorizontalOptions="FillAndExpand"
VerticalOptions="StartAndExpand">
<Label
x:Name="LabelName"
FontAttributes="Bold"
TextColor="Black"
FontSize="14"
VerticalOptions="Start"
HorizontalOptions="FillAndExpand"/>
<ListView x:Name="MultiselectList"
SeparatorVisibility="None"
RowHeight="30"
Margin="0, 10, 0, 0"
VerticalOptions="FillAndExpand"
HorizontalOptions="StartAndExpand"
SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate>
<customcontrols:NoHighlightCell>
<StackLayout Orientation="Horizontal"
HorizontalOptions="FillAndExpand"
VerticalOptions="StartAndExpand">
<Image
x:Name="image"
Source="{Binding ImageUrl}"
VerticalOptions="StartAndExpand"
HorizontalOptions="Start"
Margin="0, 2, 0, 0"
WidthRequest="15"
HeightRequest="15" />
<Label
x:Name="name"
Text="{Binding Name}"
TextColor="Black"
VerticalOptions="StartAndExpand"
FontSize="14"
HorizontalOptions="Start"/>
</StackLayout>
</customcontrols:NoHighlightCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Label Text="Selection required"
TextColor="Red"
Margin="0, 10, 0, 0"
IsVisible="{Binding ValidationRequired}"
VerticalOptions="StartAndExpand"
HorizontalOptions="FillAndExpand"
FontSize="14"/>
</StackLayout>
Here's my code behind:
private SoapNoteControlsViewModel viewModel;
public SelectListTemplate()
{
InitializeComponent();
}
protected override void OnDisappearing()
{
base.OnDisappearing();
}
protected override void OnAppearing()
{
base.OnAppearing();
LabelName.Text = viewModel.Label;
MultiselectList.ItemsSource = viewModel.CheckboxItems;
MultiselectList.SelectedItem = viewModel.SelectedItem;
//how would i set the BindingMode here? Doing .SetBinding doesn't seem to do it.
}
protected override void OnBindingContextChanged()
{
try
{
base.OnBindingContextChanged();
if(BindingContext == null)
{
return;
}
viewModel = BindingContext as SoapNoteControlsViewModel;
} catch (Exception e)
{
Console.WriteLine(e);
}
}
}
I tried doing .SetBinding, but it keeps saying that BindingMode is a type (given that it is an enum). Looking at some of the examples on MSDN haven't really helped
You would do it like this:
MultiselectList.SetBinding(ListView.ItemsSourceProperty, nameof(viewModels.CheckboxItems), BindingMode.TwoWay);
The first parameter is the property that you want to bind to - e.g. the ItemsSource.
The second parameter is the name of the property to look for - e.g. your viewModel's CheckBoxItems. This collection will be bound/populated in the list.
The last parameter is what you would want to achieve - the BindingMode. You are correct in saying that it is an enum, so here we can set it to BindingMode.TwoWay.
For reference: BindingMode's Remarks page.

I have created MasterDetailPage in MvvmCross, the click(Command) is not working on detail page

I have created an mvvm cross application in which I have created a viewmodel as well as a page with xaml.cs. So the view model is not being called from page(xaml) command or the navigation is not working.
I have attached the command :
public IMvxAsyncCommand LblTappedNumberCommand => new
MvxAsyncCommand(async
() =>
{
await _navigationService.Navigate<AddPhoneNumberViewModel>();
});
Xaml for above :
<Image Source="user.png">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding
EditProfileClicked}" NumberOfTapsRequired="1" />
</Image.GestureRecognizers>
</Image>
By removing MasterDetailPage(sidebar) above code works properly.
When I write a code for click event in xaml.cs like below it works:
xaml.cs :
public void EditProfileClicked(object sender, EventArgs args)
{
Navigation.PushAsync(new EditProfile1Page());
}
xaml :
<Image
HorizontalOptions="End"
VerticalOptions="End"
Source="user.png">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="EditProfileClicked"
NumberOfTapsRequired="1" />
</Image.GestureRecognizers>
</Image>
If you see there you are binding the command of the image to EditProfileClicked and you should be binding to LblTappedNumberCommand.

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