I am using a custom activity indicator experimenting a block on map interaction.
The map and the activity are in a grid and I use a binding property to running or not the map as:
<ContentPage>
...
<Grid>
....
<local:CustomMap HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Grid.Row="2" Grid.ColumnSpan="2"
x:Name="MyMap" IsVisible="{Binding InMap}" ItemsSource="{Binding Items}"
IsShowingUser="true" PinClicked="PinClicked"
MapType="Street"/>
<customActivity:CustomActivityIndicator
x:Name="BusyIndicator"
IsRunning= "false"
Grid.ColumnSpan="2" Grid.RowSpan="3" />
</Grid>
</ContentPage>
The problem is on the map that has bloking when user interact with it, inclusive if IsRunning is ever false.
Why it could be happen?
Your CustomActivityIndicator blocks interaction, because it's first element that you tap/touch.
You have to remove it from your grid for interacting with other view or use some hacks like setting HeightRequest=0.
Related
Is it possible to implement auto-scrolling when a user drags an item to the edge of visibible part of a CollectionView? Or StackLayout. Look's like there is no way to do this out of the box and no respective nuget packages exist. I've tried to implement this myself, but couldn't figure out which methods to override and for which of the entities. DragGestureRecognizer seemed to be promising, but still- no luck.
Here are the codes I used,drag one item to the edge and the list will scroll until reach the last item.
<ContentPage.BindingContext>
<local:PeopleViewModel/>
</ContentPage.BindingContext>
<StackLayout>
<Frame BackgroundColor="AliceBlue">
<CollectionView x:Name="mycol" ItemsSource="{Binding pgs}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Frame CornerRadius="10" BackgroundColor="LightPink">
<Label Text="{Binding Name}" FontSize="Large">
<Label.GestureRecognizers>
<DragGestureRecognizer DragStarting="OnDragstarting"/>
</Label.GestureRecognizers>
</Label>
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Frame>
</StackLayout>
</ContentPage>
I've created a custom CheckBox control to which I have added a Command/CommandParameter capability. I tried this using a Behavior and ran into the same problem. Here is my XAML:
`<ContentPage.BindingContext>
<vm:ShoppingListViewModel />
</ContentPage.BindingContext>
<ContentPage.Content>
<CollectionView ItemsSource="{Binding MyShoppingList}"
SelectionMode="None"
EmptyView="No items in your Shopping List">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="0" ColumnDefinitions="30, *, 200">
<controls:CheckBoxEx x:Name="CompletedCheckBox"
IsChecked="{Binding Completed, Mode=TwoWay}"
Command="{Binding ToggledCommand}"
CommandParameter="{Binding .}"
HorizontalOptions="Center"
VerticalOptions="Center" />
<Label Text="{Binding ItemName}" Grid.Column="1" HorizontalOptions="StartAndExpand" VerticalOptions="Center"/>
<Label Text="{Binding StoreName}" Grid.Column="2" HorizontalOptions="EndAndExpand" VerticalOptions="Center"/>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</ContentPage.Content>
`
The BindingContext for my CollectionView is clearly my ViewModel; MyShoppingList is an ObservableCollection created in the ViewModel. The CheckBox IsChecked value is located in my Model as the Completed property. The Command, however, is not found because CollectionView apparently changes the BindingContext from the ViewModel to the Model, hence the Completed, ItemName, and StoreName properties are properly bound. How can I associate the Command with the ViewModel so that the Binding occurs correctly? The purpose of the Command is to trigger a database update. Here is the runtime error I see:
[0:] Binding: 'ToggledCommand' property not found on 'ShoppingList.Models.ShoppingListItem', target property: 'GLLCustomControls.CheckBoxEx.Command'
something like this should work
Command="{Binding Source={RelativeSource AncestorType={x:Type vm:ShoppingListViewModel}}, Path=ToggledCommand}"
the Xamarin docs have multiple examples of more complex binding scenarios
I am stuck on a binding problem here.
I created a bindable layout which is inside a control template:
<ContentView x:Name="SettingsMenu" ControlTemplate="{StaticResource HeaderTemplate}" AbsoluteLayout.LayoutBounds="0.5,0.5,1,1"
AbsoluteLayout.LayoutFlags="All">
<ScrollView Orientation="Vertical" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<StackLayout x:Name="SettingsStack" BindableLayout.ItemsSource="{Binding Settings}" BindableLayout.ItemTemplateSelector="{StaticResource SettingsSelectorTemplate}" Orientation="Vertical" Spacing="0" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />
</ScrollView>
</ContentView>
What I want to do is call a command inside the view model. The call is inside a item template selector as a resource dictionary inside App.xml
<ResourceDictionary>
<DataTemplate x:Key="PlaceholderSettingsTemplate">
### SOME STUFF
</DataTemplate>
<DataTemplate x:Key="HeaderSettingsTemplate">
### SOME STUFF
<Grid ...>
<Grid.GestureRecognizers>
<TapGestureRecognizer Tapped="ButtonClick" Command="{Binding BindingContext.SettingsTap, Source={x:Reference SettingsPage}}" CommandParameter="{Binding}" /> ########## <--------- WHAT TO USE FOR SOURCE?
</Grid.GestureRecognizers>
</Grid>
</DataTemplate>
<data:SettingsSelector x:Key="SettingsSelectorTemplate" Placeholder="{StaticResource PlaceholderSettingsTemplate}" Heading="{StaticResource HeaderSettingsTemplate}" Content="{StaticResource ContentSettingsTemplate}" />
</ResourceDictionary>
Before I moved it inside a resource dictionary in the App.xml file, I simply used the x:Name of the Parent Contentview. But: I can't reference it by name anymore because I moved it into a resource dictionary inside App.xml.
Now, the answer may be trivial but I just can't find a solution.
Any help is appreciated.
Kind regards
You can find the SettingsStack StackLayout using the data template's Grid which wraps all the content. Since the SettingsStack has the same binding context as the parent content view, you can access the binding context in App.cs like:
<DataTemplate x:Key="HeaderSettingsTemplate">
<!--### SOME STUFF-->
<Grid x:Name="ParentGrid">
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Parent.BindingContext.SettingsTap, Source={x:Reference ParentGrid}}" CommandParameter="{Binding}" />
</Grid.GestureRecognizers>
</Grid>
</DataTemplate>
The ParentGrid's parent is SettingsStack on your current page.
From the item template (even if it's in a different file), you can access the view model of it's ancestor, using the following:
Command="{Binding Source={RelativeSource AncestorType={x:Type SettingsViewModel}}, Path=SettingsTap}" CommandParameter="{Binding}"
In this case I just assumed that the name of the ancestor's view model is SettingsViewModel, but you get the point.
Here is an interesting article regarding relative binding, that describes other scenarios as well: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/data-binding/relative-bindings#bind-to-an-ancestor
Cheers.
In another way we can use ContentPage as AncestorType directly. Then bind command with BindingContext.
{Binding BindingContext.SomeCommand, Source={RelativeSource AncestorType={x:Type ContentPage}}}
Complete example
<DragGestureRecognizer
DragStartingCommand="{Binding BindingContext.SomeCommand, Source={RelativeSource AncestorType={x:Type ContentPage}}}"
DragStartingCommandParameter="{Binding}"/>
Also this way works with separate resource files (eg. MySeparateResource.xml -> MyPageView.xaml).
I'm looking for a good way to implement a control that looks like a ListView with 2 columns, where each column has distinct height. As I didn't found another solution, I've decided to do it through a Repeater control.
The expected result is something like this:
All the items come from the same DataSource, and this DataSource will contain between one and a dozen of items.
The items must be splitted automatically (by modulo) into the 2 columns
When the user click on the button related to the item, this will open the item's detail page
The red squares are images that must have the same height/width
I'm working on the design of the cell DataTemplate, but I didn't see how to manage the images:
The distinction between the 2 columns is given by a Grid containing 2 Columns
Then I specify the DataTemplate for each column
<ScrollView>
<Grid Padding="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- Col.1 -->
<tabletControls:Repeater Grid.Column="0" Margin="10"
ItemsSource="{Binding ListProductItems}">
<tabletControls:Repeater.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Vertical" >
<StackLayout>
<ffimageloading:CachedImage Source="{Binding Icon}"
Aspect="AspectFill"/>
</StackLayout>
...
</StackLayout>
</ViewCell>
</DataTemplate>
</tabletControls:Repeater.ItemTemplate>
</tabletControls:Repeater>
<!-- Col.2 -->
<tabletControls:Repeater Grid.Column="1" Margin="10"
ItemsSource="{Binding ListProductItems}">
<tabletControls:Repeater.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Vertical" >
<StackLayout>
<ffimageloading:CachedImage Source="{Binding Icon}"
Aspect="AspectFill"/>
</StackLayout>
...
</StackLayout>
</ViewCell>
</DataTemplate>
</tabletControls:Repeater.ItemTemplate>
</tabletControls:Repeater>
</Grid>
</ScrollView
But this doesn't work as expected, as the image's height/width are not the same:
I already tried to play with Aspect (AspectFill, AspectFit, Fill) or VerticalOptions/HorizontalOptions, withou any result...
Is it possible to achieve the expected result without specify an HeightRequest? Are there other options?
I want to create a list view with four column, first two column will have text and next two column will have clickable button(image). Number of rows is not fixed- so data binding is require. Should support android and iOS. please suggest which xamarin control will be best suited for me.
Can i use data template as shown in https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/templates/data-templates/selector/
or should use Grid, Grid layout or any other.
======== Solution Applied=============
<ListView x:Name="listViewExpenses" CachingStrategy="RecycleElement" VerticalOptions="FillAndExpand" RowHeight="40">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="40"/>
</Grid.ColumnDefinitions>
<!--<Label x:Name="idLabel" Text="{Binding Id}"/>-->
<Label x:Name="textLabel1" Grid.Column="0" Text="{Binding Text}"/>
<!--<Button x:Name="btnEdit" Image="icon.png" HeightRequest="50" WidthRequest="50" Grid.Column="2" CommandParameter="{Binding Id}" Clicked="OnEditClicked" />-->
<StackLayout Grid.Column="1">
<Image Source="EditRed.png" VerticalOptions="Center" >
<Image.GestureRecognizers>
<TapGestureRecognizer
Tapped="OnEditTapped"
CommandParameter="{Binding Id}"/>
</Image.GestureRecognizers>
</Image>
</StackLayout>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>`enter code here`
=====================================
Thanks,
#paul
As the number of rows is not fixed but each row will look the same, I would suggest a List View with an inline data template.
https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/templates/data-templates/creating/
Data templates you mentioned is required in case of different row views. For your case Grid should be sufficient. You can add rows dynamically for example like shown here
https://forums.xamarin.com/discussion/42393/need-to-add-rows-dynamically-in-a-grid
If that doesn't work you can use ListView with custom cells
https://developer.xamarin.com/guides/xamarin-forms/user-interface/listview/customizing-cell-appearance/