How to bind to a viewmodel instead of a page - c#

My problem is with the viewcell, the OnDelete command is not found due to it being of the IssueModel class, I've attempted to change the binding-context of the Listview, but that doesn't change anything except the above binding.
Is there any way to change the binding context of the viewcell so I don't have to put the command into to IssueModel? I've attempted the below solution but I get an error
"Invalid markup extension: expected type is object, actual type is Issuepagemodel"
xmlns:pageModels="clr-namespace:ASFT.PageModels;assembly=ASFT"
<ListView ItemsSource="{Binding Issues}" SeparatorColor="#444444" RowHeight="90" IsPullToRefreshEnabled="True" IsRefreshing="{Binding IsBusy}" RefreshCommand="{Binding PullRefreshCommand}" >
<ListView.Behaviors>
<helperMethods:EventToCommandBehavior EventName="ItemSelected"
Command="{Binding OnSelectedIssueCommand}"
Converter="{StaticResource SelectedItemConverter}" />
</ListView.Behaviors>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell x:Name="Stalin">
<ViewCell.ContextActions>
<MenuItem x:Name="Hitler" Command="{Binding Path=BindingContext.OnDelete, Source={pageModels:IssueListPageModel}}" Text="Delete" IsDestructive="True" />
</ViewCell.ContextActions>
<ViewCell.View>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Image Grid.Row="0" Grid.RowSpan="3" Grid.Column="0" Source="{Binding SeverityImagePath}" HorizontalOptions="Center" VerticalOptions="Center" HeightRequest="70"/>
<Image Grid.Row="0" Grid.RowSpan="3" Grid.Column="2" Source="{Binding StatusImagePath}" HorizontalOptions="Center" VerticalOptions="Center" HeightRequest="60"/>
<Label Grid.Row="0" Grid.Column="1" Text="{Binding Title}" LineBreakMode="TailTruncation" YAlign="Center" VerticalOptions="Start" Font="Bold, Medium"/>
<Label Grid.Row="1" Grid.Column="1" Text="{Binding Created, Converter={StaticResource DateToTextConverter}}" YAlign="Center" VerticalOptions="Start" Font="Medium"/>
<Label Grid.Row="2" Grid.Column="1" Text="{Binding Description}" LineBreakMode="WordWrap" YAlign="Start" VerticalOptions="Start" Font="Small"/>
</Grid>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

Should be quite easy, if I understand your problem.
Set your page's BindingContext to your ViewModel that contains a Command with the next name "MyRootLevelCommand".
Name your root UI element:
<Grid x:Name="root"> .. </Grid>
Let's assume that within this Grid you have a ListView and you want to bind a Command from the page viewmodel to each item in the ListView:
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Button Command="{Binding Source={x:Reference root}, Path=BindingContext.MyRootLevelCommand}" />
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>

Related

How to set background image for CollectionView

How to set background image for collectionview in Xamarin.Forms?
In Colletionview "Background" is a brush and I can not adjust the image source
You can try this method:
Set the CollectionView's background setting to transparent.
<CollectionView ItemsSource="{Binding Monkeys}" BackgroundColor="Transparent">
Put Grid on the upper level of the collection view.
<Grid>
<CollectionView ItemsSource="{Binding Monkeys}" BackgroundColor="Transparent">
...
</CollectionView>
</Grid>
put a image view at the same level of the collection view.
<Grid>
<Image Source=""/>
<CollectionView ItemsSource="{Binding Monkeys}" BackgroundColor="Transparent">
<CollectionView.ItemTemplate>
...
</CollectionView>
</Grid>
Page.xaml
<Grid>
<Image Source="https://upload.wikimedia.org/wikipedia/commons/thumb/f/fc/Papio_anubis_%28Serengeti%2C_2009%29.jpg/200px-Papio_anubis_%28Serengeti%2C_2009%29.jpg"/>
<CollectionView ItemsSource="{Binding Monkeys}" BackgroundColor="Transparent">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Image Grid.RowSpan="2"
Source="{Binding ImageUrl}"
Aspect="AspectFill"
HeightRequest="60"
WidthRequest="60" />
<Label Grid.Column="1"
Text="{Binding Name}"
FontAttributes="Bold" />
<Label Grid.Row="1"
Grid.Column="1"
Text="{Binding Location}"
FontAttributes="Italic"
VerticalOptions="End" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
Screenshot

CommandParameter giving null value when use DataTemplate for listview in xamarin forms

I'm facing issue in CommandParameter which is in DataTemplate for the listView.
I have separate DataTemplate for ListView and i am not able to pass the imagepath in the commandParameter when click on image in the listView.
<?xml version="1.0" encoding="utf-8" ?>
xmlns:local="clr-namespace:RCBazaar.Localization"
xmlns:template="clr-namespace:RCBazaar.Views.Templates"
xmlns:cards="clr-namespace:PanCardView;assembly=PanCardView"
xmlns:controls="clr-namespace:PanCardView.Controls;assembly=PanCardView"
x:Class="RCBazaar.Views.HomeView" Padding="0" x:Name="HomePage">
</Style>
</ResourceDictionary>
</ContentPage.Resources>-->
<ContentPage.Content>
<Grid Style="{StaticResource MainGrid}">
<Grid.RowDefinitions>
<RowDefinition Height="140"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*" ></RowDefinition>
</Grid.RowDefinitions>
<cards:CarouselView Margin="0" x:Name="carousel" Grid.Row="0" ItemsSource="{Binding ProductImage,Mode=TwoWay}" >
<cards:CarouselView.ItemTemplate>
<DataTemplate>
<ffimageloading:CachedImage HorizontalOptions="FillAndExpand" Source="{Binding ImageName}" Style="{StaticResource CachedImageStyle}">
</ffimageloading:CachedImage>
</DataTemplate>
</cards:CarouselView.ItemTemplate>
<controls:IndicatorsControl ToFadeDuration="1500" BackgroundColor="Gray"/>
<controls:LeftArrowControl ToFadeDuration="2500" BackgroundColor="Gray" />
<controls:RightArrowControl ToFadeDuration="2500" BackgroundColor="Gray"/>
</cards:CarouselView>
<Image Grid.Row="1" Margin="0,0,10,0" Source="ic_sort.png" HeightRequest="30" WidthRequest="30" HorizontalOptions="EndAndExpand">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding SortPopupCommand}"/>
</Image.GestureRecognizers>
</Image>
<ListView IsEnabled="True" HeightRequest="{Binding ListHeight}" CachingStrategy="RecycleElement" x:Name="mylist" Style="{StaticResource ListviewStyle}" Grid.Row="2" SelectedItem="{Binding SelectedProduct,Mode=TwoWay}" ItemsSource="{Binding HomeProducts}" >
<ListView.Behaviors>
<behaviors:EventToCommandBehavior EventName="ItemSelected" Command="{Binding HomeProductSelectedCommand}"></behaviors:EventToCommandBehavior>
</ListView.Behaviors>
<ListView.ItemTemplate>
<DataTemplate>
<template:ProductCell ParentBindingContext="{Binding Source={x:Reference mylist}, Path=BindingContext}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ActivityIndicator Grid.Row="2" VerticalOptions="Start" IsVisible="{Binding IsBusy,Mode=TwoWay}" IsRunning="{Binding IsBusy,Mode=TwoWay}" Color="Blue"/>
</Grid>
</ContentPage.Content>
ProductCell
<ViewCell.View>
<Grid RowSpacing="5" Style="{StaticResource ProductTemplateGrid}" >
<Grid.RowDefinitions>
<RowDefinition Height="28*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40*"/>
<ColumnDefinition Width="60*"/>
</Grid.ColumnDefinitions>
<ffimageloading:CachedImage x:Name="img" VerticalOptions="FillAndExpand" Style="{StaticResource CachedImageStyle}" Aspect="AspectFit" Grid.Row="0" Source="{Binding PictureBinary,Converter={StaticResource Base64StringToImageConverter}}" Grid.RowSpan="5" Grid.Column="0">
<ffimageloading:CachedImage.GestureRecognizers>
<TapGestureRecognizer BindingContext="{Binding Source={x:Reference mylist}, Path=ParentBindingContext}" Command="{Binding ViewImageCommand}" CommandParameter="{Binding PictureBinary}"/>
</ffimageloading:CachedImage.GestureRecognizers>
</ffimageloading:CachedImage>
<Label Grid.Row="0" Grid.Column="1" MaxLines="2" LineBreakMode="TailTruncation" Style="{StaticResource lblDarkBody}" Text="{Binding Name}" ></Label>
<Label Grid.Row="1" Grid.Column="1" Text="{local:Translate SKU}" Style="{StaticResource lblNormal}"></Label>
<Label Margin="35,0,0,0" Grid.Row="1" Grid.Column="1" Text="{Binding upc}" Style="{StaticResource lblNormal}" />
<Label Grid.Row="2" Grid.Column="1" Text="{local:Translate Stock}" Style="{StaticResource lblNormal}" VerticalOptions="Center" ></Label>
<Image Margin="45,0,0,0" Grid.Row="2" Grid.Column="1" VerticalOptions="Center" HorizontalOptions="StartAndExpand" Source="{Binding qtyonhand,Converter={StaticResource QuantityToColorConverter}}" />
<uc:CustomRatingBar Grid.Row="3" Grid.Column="1" Style="{StaticResource RatingsStyle}" x:Name="CusRatingBar" Rating="{Binding RatingSum}" />
<Image Grid.Row="4" Grid.Column="1" Source="in.png" HorizontalOptions="Start" VerticalOptions="Center"/>
<Label Margin="30,0,0,0" Grid.Row="4" Grid.Column="1" VerticalOptions="Center" Style="{StaticResource lblEmphasis}" Text="{Binding pricelist,StringFormat='Rs {0:#,0.#0}'}" ></Label>
<Image Grid.Row="4" Grid.Column="1" Margin="0,0,10,0" WidthRequest="30" HeightRequest="30" VerticalOptions="Center" Style="{StaticResource StockCachedImageStyle}" Source="heartdark.png" HorizontalOptions="End">
<Image.GestureRecognizers>
<TapGestureRecognizer BindingContext="{Binding Source={x:Reference mylist}, Path=ParentBindingContext}" Command="{Binding AddtoWishlistCommand}" CommandParameter="{Binding .}" />
</Image.GestureRecognizers>
</Image>
</Grid>
</ViewCell.View>
If you give the page in question an x:Name in your XAML you can then refer to the origional BindingContext (should be your ViewModel) while also having access to the item itself as BindingContext for the commandparameter. Looks something like this:
<ContentPage x:Name="MyContentPage"
....
<!--inside your DataTemple you can now reference the BindingContext of your page-->
Command="{Binding Path=BindingContext.HomeProductSelectedCommand, Source={x:Reference MyContentPage}} CommandParameter="{Binding .}"
…
This example passes the bindingcontext of the item (by default that's the item itself) to the command parameter

Xamarin WebView inside TableView lost value

I have a WebView filled with an HTML code that came from database.
This WebView is inside a TableView.
This is the XAML code:
<TableView Intent="Form" HasUnevenRows="True" Margin="0,0,0,0">
<TableRoot>
<!--#region Nota-->
<TableSection Title="{core:Translate LblNota}">
<ViewCell>
<ViewCell.View>
<StackLayout>
<Label BackgroundColor="Purple" Text="{Binding NotaRigaHtml}" Style="{StaticResource LblDescrizione}" />
<WebView IsEnabled="False" HeightRequest="200" Source="{Binding NotaRigaHtml}"/>
</StackLayout>
</ViewCell.View>
</ViewCell>
</TableSection>
<!--#endregion-->
<!--#region Lista Tecnici -->
<TableSection Title="{core:Translate Tecnici}">
<ViewCell>
<ViewCell.View>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ListView Grid.Row="0" Grid.Column="0" x:Name="ListaTecniciIntervento" HasUnevenRows="True" SeparatorVisibility="None" ItemsSource="{Binding ListaTecnici}" HeightRequest="{Binding AltezzaListaTecnici}">
<ListView.ItemTemplate>
<DataTemplate>
<view:TecniciInterventoViewCell Pagina="{x:Reference RigaDettaglioPage}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</ViewCell.View>
</ViewCell>
</TableSection>
<!--#endregion-->
<!--#region Passaggio successivo-->
<TableSection Title="{core:Translate LblPassaggioSuccessivo}">
<ViewCell>
<ViewCell.View>
<Grid Style="{StaticResource GridPadding}" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Text="{core:Translate LblProgressStatus}" Grid.Row="0" Grid.Column="0" />
<Picker Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="3"/>
<Label Text="{core:Translate LblProgressStatusLevel}" Grid.Row="1" Grid.Column="0" />
<Picker Grid.Row="1" Grid.Column="1" />
<Label Text="{core:Translate utente}" Grid.Row="1" Grid.Column="2" />
<Picker Grid.Row="1" Grid.Column="3" />
<Label Text="{core:Translate LblProgressStatusInstallatore}" Grid.Row="2" Grid.Column="0" />
<Picker Grid.Row="2" Grid.Column="1" />
<Label Text="{core:Translate LblProgressStatusTecnico}" Grid.Row="2" Grid.Column="2" />
<Picker Grid.Row="2" Grid.Column="3" />
</Grid>
</ViewCell.View>
</ViewCell>
</TableSection>
<!--#endregion-->
</TableRoot>
</TableView>
When the WebView go off the screen, the values disappears.
How can I avoid this behavior?
Why the WebView is cleared?
Thank you!
EDIT:
I have find that the problem is the ListView.
When an Item of the ListView is outside of the screen, this problem is triggered, but I can't solve :(

Xamarin forms Android Listview issue with ContextActions and GestureRecognizer

I'm writing an xamarin forms app. I have A ListView with custom cell (xaml):
<ViewCell>
<ViewCell.ContextActions>
<MenuItem Clicked="Btn_delete_Clicked" CommandParameter="{Binding .}" Text="Удалить" IsDestructive="True" />
</ViewCell.ContextActions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image Source="{Binding Image}" Grid.Row="0" Grid.Column="0" Margin="5" VerticalOptions="Center"
HorizontalOptions="Center" Aspect="AspectFit" WidthRequest="170" HeightRequest="170" >
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="Btn_fullscr_Clicked" />
</Image.GestureRecognizers>
</Image>
<Entry x:Name="EditTextPhoto" Placeholder="[Комментарий отсутствует]" Grid.Row="1" Grid.Column="0"
Margin="5" VerticalOptions="FillAndExpand" HorizontalOptions="Fill" FontSize="14"
Text="{Binding Comment}" BackgroundColor="#44104e8b" IsEnabled="{Binding IsPreview}" TextColor="Black" HorizontalTextAlignment="Center" />
</Grid>
</ViewCell>
As you can see, I have ContextActions and a TapGestureRecognizer for my Image.
A have a bug on android: if you click on a view cell, the contextaction appears. ContextAction has to be done only on long press, as you know. But when I remove gesturerecognizer from Image, everything works fine.
Does anybody know how to workaround this issue? Thanks in advance.
Finally I've found a workaround for this issue. I added a transparent button in the same row where my image is and deleted tapgesturerecognizer. So the final code is:
<ViewCell>
<ViewCell.ContextActions>
<MenuItem Clicked="Btn_delete_Clicked" CommandParameter="{Binding .}" Text="Удалить" IsDestructive="True" />
</ViewCell.ContextActions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image Source="{Binding Image}" Grid.Row="0" Grid.Column="0" Margin="5" VerticalOptions="Center"
HorizontalOptions="Center" Aspect="AspectFit" WidthRequest="170">
</Image>
<Button Grid.Row="0" Grid.Column="0" HorizontalOptions="Center" Clicked="Btn_fullscr_Clicked"
WidthRequest="170" VerticalOptions="FillAndExpand" BackgroundColor="Transparent" BorderColor="Transparent" />
<Entry x:Name="EditTextPhoto" Placeholder="[Комментарий отсутствует]" Grid.Row="1" Grid.Column="0"
Margin="5" VerticalOptions="FillAndExpand" HorizontalOptions="Fill" FontSize="14"
Text="{Binding Comment}" IsEnabled="{Binding IsPreview}" TextColor="Black" HorizontalTextAlignment="Center" />
</Grid>
</ViewCell>
Hope maybe it helps someone in future!

I can't run applicaton when using '<ViewCell.ContextActions>' on Xamarin Form (PCL)?

Severity Code Description Project File Line Suppression State
Error Position 37:61. Type Regerence not found in xmlns http://schemas.microsoft.com/winfx/2009/xaml Course_3
<ViewCell>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<Image Source="{Binding PhotoUrl}" HeightRequest="70"></Image>
</Grid>
<StackLayout Grid.Column="1" Padding="5">
<Label Text="{Binding FullName}" FontSize="15" TextColor="Black" Margin="0,5"></Label>
<Label Text="{Binding City}" FontSize="10" TextColor="Black" Margin="0,5"></Label>
<Label Text="{Binding JobTitle}" FontSize="10" TextColor="#CCCCCC" Margin="0,5"></Label>
</StackLayout>
<ViewCell.ContextActions>
<MenuItem Text="Edit" Command="{Binding Source={x:Reference Root}, Path=BindingContext.EditCommand}"
CommandParameter="{Binding}"></MenuItem>
<MenuItem Text="Delete" Command="{Binding Source={x:Regerence Root},Path=BindingContext.DeleteCommand}"
CommandParameter="{Binding}"></MenuItem>
</ViewCell.ContextActions>
</Grid>
</ViewCell>
You should move the <ViewCell.ContextActions> part outside of the Grid control. It needs to be a direct child of ViewCell. Don't know if this is a type you also made in code but change {x:Regerence Root} to {x:Reference Root} for the second menu item. Also your question would probably benefit from some editing to improve its overall quality.
<ViewCell>
<ViewCell.ContextActions>
<MenuItem Text="Edit" Command="{Binding Source={x:Reference Root}, Path=BindingContext.EditCommand}"
CommandParameter="{Binding}"></MenuItem>
<MenuItem Text="Delete" Command="{Binding Source={x:Reference Root},Path=BindingContext.DeleteCommand}"
CommandParameter="{Binding}"></MenuItem>
</ViewCell.ContextActions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<Image Source="{Binding PhotoUrl}" HeightRequest="70"></Image>
</Grid>
<StackLayout Grid.Column="1" Padding="5">
<Label Text="{Binding FullName}" FontSize="15" TextColor="Black" Margin="0,5"></Label>
<Label Text="{Binding City}" FontSize="10" TextColor="Black" Margin="0,5"></Label>
<Label Text="{Binding JobTitle}" FontSize="10" TextColor="#CCCCCC" Margin="0,5"></Label>
</StackLayout>
</Grid>
</ViewCell>

Categories