Access property in ListView that is not coming from ItemsSource - xaml

My ListView is bound to MyTexts list. Nevertheless i need to bind TextCell's Text to property that is not comming from Texts (StandAloneProperty). How can i do that?
<ListView
SelectedItem="{Binding SelectedText, Mode=TwoWay}"
ItemsSource="{Binding MyTexts}">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell
Text="{Binding StandAloneProperty, StringFormat='Value: {0}'}"
TextColor="{Binding Color}"
/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

Set your binding Source to the current page, and access to StandAloneProperty, from BindingContext which is your ViewModel.
<ContentPage x:Name="pageRef"
...
<ListView
SelectedItem="{Binding SelectedText, Mode=TwoWay}"
ItemsSource="{Binding MyTexts}">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell
Text="{Binding Source={x:Reference pageRef} Path=BindingContext.StandAloneProperty, StringFormat='Value: {0}'}"
TextColor="{Binding Color}"
/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

Related

WinUI3 - bind ContentControl to CollectionViewSource CurrentItem instead of collection?

When an item is selected in my ListView, I want to display a specific user control in the my ContentControl.
Using the following code, my content control merely displays "Microsoft.UI.Xaml.Data.CollectionView". I understand the ContentControl is trying to bind to the entire list, but how do I tell it to bind to the CollectionViewSource's CurrentItem?
<Page.Resources>
<CollectionViewSource x:Name="PChoicesCollectionView" Source="{x:Bind ViewModel.PChoices}"/>
</Page.Resources>
<ListView ItemsSource="{Binding Source={StaticResource PChoicesCollectionView}}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="p:PBase">
<Grid>
<TextBlock Text="{x:Bind Name.Name}" FontSize="18" FontWeight="SemiBold"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ContentControl ContentTemplateSelector="{StaticResource pDataTemplateSelector}" Content="{Binding Source={StaticResource PChoicesCollectionView}}"/>
You could bind to the SelectedItem property of the ListView:
<ListView Name="lv"
ItemsSource="{Binding Source={StaticResource PChoicesCollectionView}}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="p:PBase">
<Grid>
<TextBlock Text="{Binding}" FontSize="18" FontWeight="SemiBold"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ContentControl ContentTemplateSelector="{StaticResource pDataTemplateSelector}"
Content="{Binding SelectedItem, ElementName=lv}"/>

Conditional text in Xamarin Forms

How do I conditionally render a particular text in Xamarin Forms 5?
For example, I get some data from my API backend for a vendor and there may be an address in the database for this vendor or not.
If I do have vendor's address, I'd like to display it and if I don't have an address, I'd like to display something like "n/a".
Is there a way to handle this in the XAML page or do I have to handle it in code behind?
UPDATE:
Here's what the XAML page for the phone numbers ListView looks like:
<Grid Grid.Row="1" Grid.Column="0" RowDefinitions="150, *" ColumnDefinitions="250, 250">
<StackLayout
Grid.Row="0"
Grid.Column="0"
Padding="10">
<ListView
BackgroundColor="Transparent"
SeparatorVisibility="None"
ItemsSource="{Binding Contact.PhoneNumbers, TargetNullValue='n/a'}">
<ListView.Header>
<StackLayout>
<Label Text="Phone Number(s)"
FontAttributes="Bold"/>
</StackLayout>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding PhoneNumberDisplay}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</Grid>
You can use xaml binding with TargetNullValue
<Label Text="{Binding Location, TargetNullValue='n/a'}"/>
If you don't have an address your API or your code should set Location to null in order for TargetNullValue to work.
Update (reply to this comment).
Use TargetNullValue in the bindings inside ItemTemplate (applies to each single element) and not on itemsource binding:
<Grid Grid.Row="1" Grid.Column="0" RowDefinitions="150, *" ColumnDefinitions="250, 250">
<StackLayout
Grid.Row="0"
Grid.Column="0"
Padding="10">
<ListView
BackgroundColor="Transparent"
SeparatorVisibility="None"
ItemsSource="{Binding Contact.PhoneNumbers}">
<ListView.Header>
<StackLayout>
<Label Text="Phone Number(s)"
FontAttributes="Bold"/>
</StackLayout>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding PhoneNumberDisplay, TargetNullValue='n/a'}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</Grid>

How to set margin around ImageCell in Xamarin.Forms?

I want to have some space around the Image cell items of a ListView:
<StackLayout>
<ListView ItemsSource="{Binding Items}" HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ImageCell Text="{Binding Title}" ImageSource="{Binding Image}" TextColor="Black" DetailColor="Gray"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
but there's no Margin property available for the ImageCell?
EDIT
I did what cvanbeek suggested before posting the question:
<DataTemplate>
<StackLayout Padding="5">
<ImageCell Text="{Binding Title}" ImageSource="{Binding Image}" TextColor="Black" DetailColor="Gray"/>
</StackLayout>
</DataTemplate>
but I got this exception:
Unhandled Exception:
System.InvalidCastException: Specified cast is not valid.
in the OnCreate method in MainActivity.cs
DataTemplate definition
Only View can be put inside DataTemplate, however StackLayout is Layout.
Use a ViewCell instead , it is more flexible and controllable.
<ListView >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="20" Orientation="Horizontal" >
<Label Margin="20" Text="123"/>
<Image Source="Assets/StoreLogo.png"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

ListViewItem access property on viewmodel

I have a list of users on my viewmodel that I pass to the following listView:
<ListView
Background="Azure"
x:Name="ContactList"
ItemsSource="{Binding Path=User}"
SelectedItem="{Binding SelectedUser, Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate>
<Border Width="300" Height="Auto" BorderThickness="1">
<StackPanel>
<TextBlock>
<Run Text="{Binding Name}" />
<Run Text="{Binding Age}" />
</TextBlock>
<CheckBox Visibility="{???}">
<TextBlock FlowDirection="LeftToRight"></TextBlock>
</CheckBox>
</StackPanel>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
As you can see my DataTemplate contains a checkbox. I would like its Visibility to depend on a bool-property I have on my ViewModel. How can I access this property from within the listView?
From looking around here it seems like there are ways to access the ListView-items parent. I think that would do it for me. Can someone point me in the right direction . Thanks
The best way to do this is to include the visibility setting along with your user data. Assuming your view model visibility property is named CheckBoxVisibility, you would have something like this:
<ListView ItemsSource="{Binding}" ...>
<ListView.ItemTemplate>
<DataTemplate>
...
<Run Text="{Binding Path=User.Name}" />
<Run Text="{Binding Path=User.Age}" />
...
<CheckBox Visibility="{Binding Path=CheckBoxVisibility}">
...
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
In WPF, you can use a RelativeSource=RelativeAncestor binding; however, this is not available in Window Store/Windows Phone 8+ apps.

Access property of DataContext in ItemTemplate

My datacontext has two properties: Items which is a collection and DetailsVisiblity which is enum of type Visiblity.
On the page I have a Listbox with ItemsSource="{Binding Entries}". Inside the DataTemplate, I can bind stuff to properties of Items, but how do I get access to DetailsVisiblity which is a property of DataContext?
DataContext has two properties: ObservableCollection<Item> Entries, and Visibility DetailsVisiblity. Item class has two properties: Title and Details.
Here is the view. How do I bind Visiblity of the second TextBlock to DetailsVisiblity property?
<ListBox ItemsSource="{Binding Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Title}" />
<TextBlock Text="{Binding Details}" Visibility="{Binding ???}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
You could name the ListBox and in the Binding you reference it with ElementName, and in Path you use DataContext.DetailsVisibility
<ListBox x:Name="listBox" ItemsSource="{Binding Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Title}" />
<TextBlock Text="{Binding Details}"
Visibility="{Binding ElementName=listBox,
Path=DataContext.DetailsVisibilty}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>