DataBinding ListView ItemTemplate UserControl - xaml

I have a ListView on my Windows Universal page. I am using a UserControl to define my ItemTemplate so that I can use the RelativePanel and VisualStateManager to control how my items appear depending on the screen size...
<ListView ItemsSource="{Binding Path=AllThings}"
ItemContainerStyle="{StaticResource ListViewItemStyle}">
<ListView.ItemTemplate>
<DataTemplate>
<local:CrossingControl />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I have a button in my UserControl where I want to bind its Command to a command property in the ViewModel that is the DataContext of the list itself...
<UserControl ...>
<RelativePanel>
<StackPanel x:Name="crossedEntryPanel">
<Button Command="{Binding DataContext.DeleteCommand,
RelativeSource={RelativeSource Mode=TemplatedParent}}"
CommandParameter="{Binding}"
I have tried using the ElementName binding, but it doesn't seem to work (I suppose because my listview element name is defined in another xaml file). I have also tried the above RelativeSource binding, but that doesn't seem to work either. How can I bind this properly?

You can make use of Tag property to save the DataContext of ListView and use it in UserControl
Here how it is done
<ListView ItemsSource="{Binding Path=AllThings}" x:Name="listview"
ItemContainerStyle="{StaticResource ListViewItemStyle}">
<ListView.ItemTemplate>
<DataTemplate>
<local:CrossingControl Tag="{Binding DataContext,ElementName=listview}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<UserControl x:Name="usercontrol" ...>
<RelativePanel>
<StackPanel x:Name="crossedEntryPanel">
<Button Command="{Binding Tag.DeleteCommand,ElementName=usercontrol}"
CommandParameter="{Binding}"
RelativeSource={RelativeSource Mode=TemplatedParent}}":- this points to controltemplate of button

Related

UWP: How to catch the click of a listview part from another listview in the viewmodel instead of code-behind?

I have this listview:
<Page
x:Class="DataBase.ControlsPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DataContext="{Binding CustomersViewModel, Source={StaticResource ViewModelLocator}}">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ListView Name="HeaderList" ItemsSource="{Binding Customers}">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Border Background="Bisque">
<TextBlock Text="{Binding Name"/>
</Border>
<ListView Name="SubItemsList" ItemsSource="{Binding Project}" ItemClick="SubItemClick">
<x:String>SubItem 1</x:String>
<x:String>SubItem 2</x:String>
<x:String>SubItem 3</x:String>
</ListView>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
<x:String>Item 1</x:String>
<x:String>Item 2</x:String>
<x:String>Item 3</x:String>
</ListView>
</Grid>
</Page>
All I want is to catch the click of a subItem(ItemClick="SubItemClick">) in my CustomersViewModel. Is that possible? I know for the sub-items list items, the data is a Project which is just a data model, it does not contain any click handler. But, how can I catch the click in the view model and not in the code-behind?
Also I'm uploading a picture to visualise what I want:
What you really need is a ClickCommand in your viewmodel. But since the ListView control doesn't expose a ItemClickCommand, one common way is to use a behavior to establish the connection between your ClickCommand and the ItemClick event.
This particular behavior you are looking for is called InvokeCommandAction, which can be found in this nuget package.
Basically the end result would look something like this -
<ListView Name="HeaderList" ItemsSource="{Binding Customers}">
<Interactivity:Interaction.Behaviors>
<Interactions:EventTriggerBehavior EventName="ItemClick" SourceObject="{Binding ElementName=HeaderList}">
<Interactions:InvokeCommandAction Command="{Binding ClickCommand}"/>
<Interactions:EventTriggerBehavior>
<Interactivity:Interaction.Behaviors>
As Justin XL said, the answer I was looking for is this:
ItemClick="{Binding DataContext.ClickCommand, ElementName=HeaderList}"

How to bind FontSize of Label inside a ListView

I have a ListView whose ItemSource is binded to ArticleList. I need to Bind the FontSize of the Label inside it to MyFontSize which is NOT inside ArticleList. Its just another property in my view model, just like ArticleList
XAML code:
<ListView ItemsSource="{Binding ArticleList}"
x:Name="ArticleListView" HasUnevenRows="True"
SeparatorVisibility="None">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<ContentView>
<StackLayout Padding="10,0,20,10">
<Image Source="{Binding _Image}"/>
<Label Text="{Binding _Description}"
FontSize="{Binding MyFontSize}"/>
</StackLayout>
</ContentView>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
You need to 'target' the element which holds the correct datacontext for your ViewModel. I would guess you hooked it up to your page? Anyhow, the syntax is as follows - with elementname the element with the correct datacontext.
{Binding DataContext.MyFontSize, ElementName=LayoutRoot}
Great catch by Dushyant Bangal, seems in Xamarin you need to use the Source property for the binding to work :)
FontSize="{Binding BindingContext.MyFontSize, Source={Reference LayoutRoot}}"
Try something like this:
FontSize="{Binding ElementName=ArticleListView, Path=DataContext.MyFontSize}"

How to change the parent of DataContext in xaml in Windows phone 8.1

I have this xaml in windows phone 8.1.
My page data context is binded to a ViewModel, i.e. VM.
And My listView is binded to Items of ViewModel.
And the text in each list view item is binded to Text of Items of ViewModel.
<Page DataContext="{Binding VM}">
<ListView ItemsSource="{Binding Items}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Text}"/>
<TextBox Text="{Binding soemthing in VM}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Page>
My question is how can I change the parent datacontext of my 2nd TextBox so that I can bind something in my ViewModel (not my ViewModel.Items)?
Thank you.
If you don't mind Element Binding,
<ListView ItemsSource="{Binding Items}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Text}"/>
<!-- Bind the DataContext directly to the whatever element you like, in this case the page, then the Text Binding is basically the DataContext.VM_Property -->
<TextBlock Text="{Binding DataContext.VM_Property}" DataContext="{Binding ElementName=page}" ></TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

Bind ListBox in DataTemplate to parent control DataMemberBinding - Silverlight XAML

Just wondering if it's possible to bind the listbox in the XAML below to the GridViewDataColumn in a relative manner - I can do it explicitly but I want to add the Columns dynamically and would like to set up some logic in the the Column's Converter.
<navigation:Page.Resources>
<converters:DebugConverter x:Key="DebugConverter"/>
<converters:DebugInnerConverter x:Key="DebugInnerConverter"/>
<DataTemplate x:Key="ChemistryResultsTemplate">
<ListBox><!-- Bind this to parent GridViewDataColumn data -->
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ProfileResult}"></TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</navigation:Page.Resources>
<Grid x:Name="LayoutRoot">
<telerik:RadGridView x:Name="LabReportGrid" AutoGenerateColumns="True">
<telerik:RadGridView.Columns>
<telerik:GridViewDataColumn DataMemberBinding="{Binding ChemistryResults, Converter={StaticResource DebugConverter}}"
CellTemplate="{StaticResource ChemistryResultsTemplate}"
x:Name="Testing">
</telerik:GridViewDataColumn>
</telerik:RadGridView.Columns>
</telerik:RadGridView>
</Grid>

How to get control parent DataContext for element to element databinding?

Suppose I have a user control which datacontext is bound to a VM. This VM has a property for a list MyList.
Inside this user control I have a ComboBox, I want to set following kind of xaml
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel HorizontalAlignment="Stretch">
<sdk:DataGrid ItemsSource="{Binding YourList}" IsReadOnly="True" AutoGenerateColumns="False" >
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn Header="Name" Binding="{Binding Name}" />
<!-- ...... -->
<sdk:DataGridTemplateColumn Header="User" >
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding ElementName=LayoutRoot, Path=DataContext.MyList}" DisplayMemberPath="Value" SelectedValuePath="Key" SelectedValue="{Binding UserID}" ></ComboBox>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
</sdk:DataGrid.Columns>
</sdk:DataGrid>
</StackPanel>
</Grid>
but it is not working.
How to resolve this problem?
This worked form me. This was the ItemSource for a ComboBox that was within a DataGrid:
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=sdk:DataGrid},
Path=DataContext.Teams}">
Are you trying to get to the main VM from within the UserControl? take a look at this solution. http://weblogs.asp.net/dwahlin/archive/2009/08/20/creating-a-silverlight-datacontext-proxy-to-simplify-data-binding-in-nested-controls.aspx