I have a Xamarin BindingContext quandary - xamarin

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

Related

Xamarin PCL. Scrolling while Dragging

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>

Xamarin Carousel View: Align current item center when peaking?

I have a Xamarin Carousel view with the PeakAreaInsets set pretty high so that I can see multiple items in the list at once. However I notice that the current item when set to snap, aligns it self more with the top of the page when I would like it to snap to the center of the page. How can I accomplish this?
Here is a snippet of the code in question:
<ContentPage.Content>
<CarouselView ItemsSource="{Binding Days}"
CurrentItem="{Binding SelectedDay}"
VerticalOptions="Center"
HorizontalOptions="Center"
PeekAreaInsets="300"
x:Name="DayCarousel">
<CarouselView.ItemsLayout>
<LinearItemsLayout SnapPointsAlignment="Center"
SnapPointsType="Mandatory"
Orientation="Vertical"/>
</CarouselView.ItemsLayout>
<CarouselView.ItemTemplate>
<DataTemplate>
<StackLayout Spacing="0"
Orientation="Vertical"
HorizontalOptions="Center"
VerticalOptions="Center"
Margin="30,10">
<Label Text="{Binding FormattedDate}"
HorizontalOptions="Center"
VerticalOptions="Center"
Style="{StaticResource LabelStyle}"/>
<Label Text="{Binding TitleText}"
HorizontalOptions="Center"
VerticalOptions="Center"
Style="{StaticResource LabelHeader1Style}"/>
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Command="{Binding BindingContext.SelectDay, Source={x:Reference this}}"
CommandParameter="{Binding .}"/>
</StackLayout.GestureRecognizers>
</StackLayout>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</ContentPage.Content>
Here is about what it looks like now (just a mock up):
And here is what I would like it to look like:
I ended up playing around with it for a bit. I'm not sure how its going to look on other phone formats and sizes since I haven't tested that yet. But eventually I found a happy medium after tweaking the PeakAreaInsets, and adjusting the SnapPointsAlignment. Currently I have it set to PeakAreaInsets = 350 and SnapPointsAlignment="Start"

Xamarin.Forms iOS transparent ListView heading issue

I'm making a simple listview and got a problem with iOS header - I want to make it transparent, but the problem is, that listview items are sliding under heading. What I want to achieve, is that heading will slide up with listview items.
This is how it looks now
And this is how current code looks like:
<ListView x:Name="SingleBeanView"
ItemsSource="{Binding Beans}"
IsGroupingEnabled="true"
Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"
BackgroundColor="Transparent">
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell ios:Cell.DefaultBackgroundColor="Transparent" Height="52">
<Label Text="{Binding Heading}" TextColor="{StaticResource LightTextColor}" FontSize="Large" HorizontalOptions="Start" VerticalOptions="Start" Margin="15,10,0,0"/>
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout BackgroundColor="Transparent" Orientation="Vertical">
<StackLayout Orientation="Horizontal">
<Label Text="{Binding Field1}"/>
<Label Text="{Binding Field2}"/>
<Label Text="{Binding Field3}"/>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Unfortunately , if using GroupHeader in ListView , this can not achieve your want.This effect is designed by Apple . If want to modify ,this need more things and time to do about customing listview.
Here is a solution for native ios, you can have a try with custom renderer to do.However, after testing this can not work in Xamarin.
So the last way maybe need custom cell to realize it--Puttinng header in Cell . Then That means you can not use GroupHeaderTemplate.
Another discussion.

Xamarin binding Reference is it needed for every element?

I have this code in my application:
<StackLayout x:Name="pfs" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<StackLayout Grid.Row="0" Grid.Column="1" Padding="0,0,20,0" Orientation="Horizontal"
HorizontalOptions="EndAndExpand" VerticalOptions="CenterAndExpand">
<Label x:Name="scoreCountLabel"
TextColor="{Binding BindingContext.TickMarkColor, Source={Reference pfs}}"/>
</StackLayout>
I am trying to understand how the TextColor is set. Can someone explain to me why the developer has set the Source={Reference pfs}
Why is this needed as it's already inside a StackLayout with the name of pfs?
It's completely unnecessary from what I can tell. BindingContext is inherited by all subviews, so referencing the parent view's BindingContext is redundant.
TextColor="{Binding TickMarkColor}"/>
Done.

MvvmCross Windows Phone 8.1 bind list selection to command, compilation failure

I've the following error:
Object of type Windows.UI.Xml.Controls.ListView cannot be converted to type System.Windows.DependencyObject
Due to the following code:
<ListView Grid.Row="1" ItemsSource="{Binding Cases}" IsItemClickEnabled="False" SelectionMode="Single">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="{Binding Subject}" HorizontalAlignment="Left"></TextBlock>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding ShowCaseCommand, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ListView>
I added EventTrigger to the namespace like so:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
I added Interaction to the project by adding a reference manually from C:\Program Files (x86)\Microsoft SDKs\Expression\Blend\.NETFramework\v4.5\Libraries\System.Windows.Interactivity.dll.
Of course removing the <i:Interaction.Triggers> block eliminates the error but I need to bind selection to a command, like I do in UIKit and Android.
So – what manner of deviltry is this?
The problem is that this code is not compatible with Windows Phone 8.1.
The list view needs to be set up like so:
<ListView Grid.Row="1" ItemsSource="{Binding Cases}" IsItemClickEnabled="False" SelectionMode="Single">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="{Binding Subject}" HorizontalAlignment="Left"></TextBlock>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="SelectionChanged">
<core:InvokeCommandAction Command="{Binding ShowCaseCommand, Mode=OneWay}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</ListView>
One needs to add a reference to the Behaviors library, not Windows.Interaction.
The code above requires the following attributes on the root node:
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
This leads to another problem; while it will be bound to ShowCaseCommand, it will pass in instance of SelectionChangedEventArgs, rather than the selected list item.
We solve this with CommandParameter.
We add an attribute to the ListView, like so – <ListView Name='listView' ... – and this name allows us to refer to it later:
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="SelectionChanged">
<core:InvokeCommandAction Command="{Binding ShowCaseCommand, Mode=OneWay}" CommandParameter="{Binding ElementName=listView, Path=SelectedItem}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
By specifying the command parameter like this, we can pass the selected item as the parameter, making it compatible with the same sort of selection command one uses in iOS.

Resources