Define listview in resource file with only ItemSource changing - xaml

I created the following ListView to display some data (removed extraneous markup):
<ListView ItemsSource="{Binding NewYorkResidents}">
<ListView.Header>
<Style>
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
</Style>
</ListView.Header>
<ListView.HeaderTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="Name" Grid.Column="0" />
<TextBlock Text="Address" Grid.Column="1" />
</Grid>
</DataTemplate>
</ListView.HeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}" Grid.Column="0" />
<TextBlock Text="{Binding Address}" Grid.Column="1" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Now I want to reuse this exact same ListView + markup in a different view, just with a different ItemsSource (though it will bind to the same data type).
What is the best way to reuse the ListView and just specifiy the ItemsSource? I'm hoping to be able to do something like this:
<ListView DataTemplate="MyTemplate" ItemsSource=<some new binding> />
and still have it show the ListView headers and Name and Address TextBlocks using data from the ItemsSource.
Making a ControlTemplate doesn't seem like the right thing because I am specifiying actual data in the list view also (such as binding to name and address).
Is there a better way to create some type of resource so I can reuse this?

Define the header template and item template in resource dictionary and add reference of them in your code. you can reuse this templates.
<DataTemplate x:Key="HeaderTemplate1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="Name" Grid.Column="0" />
<TextBlock Text="Address" Grid.Column="1" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="ListViewTemplate1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}" Grid.Column="0" />
<TextBlock Text="{Binding clothing1}" Grid.Column="1" />
</Grid>
</DataTemplate>
<ListView HeaderTemplate="{StaticResource HeaderTemplate1}" ItemTemplate="{StaticResource ListViewTemplate1}"/>
for more information on Item template:
https://learn.microsoft.com/en-us/windows/uwp/controls-and-patterns/listview-item-templates

Related

XAML Grid Column Widths not matching

I am making a table in UWP (I am very new to UWP so go easy on me! Maybe even suggest a way that it is ten times better to implement this) that dynamically loads the data. This is the XAML code for it:
<ListView x:Name="ShiftListView" Grid.Column="0">
<ListView.HeaderTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" x:Name="HeaderColumn"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="Location" Grid.Column="0"/>
<TextBlock Text="Role" Grid.Column="1"/>
<TextBlock Text="Date" Grid.Column="2"/>
<TextBlock Text="Start" Grid.Column="3"/>
<TextBlock Text="Finish" Grid.Column="4"/>
</Grid>
</DataTemplate>
</ListView.HeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Location}" Grid.Column="0"></TextBlock>
<TextBlock Text="{Binding Role}" Grid.Column="1"></TextBlock>
<TextBlock Text="{Binding Date}" Grid.Column="2"></TextBlock>
<TextBlock Text="{Binding Start}" Grid.Column="3"></TextBlock>
<TextBlock Text="{Binding Finish}" Grid.Column="4"></TextBlock>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
The column definitions are done in the exact same way for both grids however the first one is the only one that stretches out to fill the entire available space but the other works as if I have inputted auto and only scaling to the size of the content. I have tried to bind the widths of the second set of columns to the first set but it doesn't change anything.
<ColumnDefinition Width="{Binding ElementName=HeaderColoumn, Path=ActualWidth"/>
But alas this did not work.
Here is a screenshot of the problem
Appending ItemContainerStyle to the ListView, specify HorizontalContentAlignment=Stretch.
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Padding" Value="0"/>
</Style>
</ListView.ItemContainerStyle>

UWP - Can I bind a textblock in a datatemplate to a grid column's width outside of it?

Relatively new to UWP, is it possible to bind a TextBlock of a DataTemplate (used for ItemTemplate in a listview) to a column outside of it, or is there any way to set the DataTemplate's grid columns' widths to the size of the "MainGrid"'s column definition widths? Code below to show what I'm trying to achieve.
<Grid x:Name="MainGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="Column1" Width="*"/>
<ColumnDefinition x:Name="Column2" Width="8*"/>
<ColumnDefinition x:Name="Column3" Width="*"/>
</Grid.ColumnDefinitions>
<ListView Name="recordList" ItemsSource="{x:Bind _recordingList, TargetNullValue=0}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:Recording">
<Grid>
<TextBlock Grid.Column="{Binding Column1}" Name="TextBlock_Time" Text="{x:Bind Time}"/>
<TextBlock Grid.Column="{Binding Column2}" Name="TextBlock_Message" Text="{x:Bind Message}"/>
<TextBlock Grid.Column="{Binding Column3}" Name="TextBlock_Type" Text="{x:Bind Type}"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
With the image below, I suppose imagine the red lines are the window. Essentially trying to get the columns to adapt to the window size changing.
example
I think you want listviewitem to be streched to the size of window. To achieve that you need to set HorizontalContentAlignment of listviewitem has to set to stretch in ItemContainerStyle
<ListView x:Name="MessagesList" BorderThickness="1" ItemsSource="{x:Bind _recordingList, TargetNullValue=0}" BorderBrush="Black">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
<Setter Property="Padding" Value="0"></Setter>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:Recording">
<Grid BorderThickness="0,1,0,0" Padding="20" BorderBrush="{ThemeResource SystemControlForegroundBaseMediumBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="8*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{x:Bind Time,Mode=OneWay}"></TextBlock>
<TextBlock Grid.Column="1" Text="{x:Bind Message,Mode=OneWay}"></TextBlock>
<TextBlock Grid.Column="2" Text="{x:Bind Type,Mode=OneWay}"></TextBlock>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
You just need to move your columns to the template itself.
DataTemplate is a scheme that describes what and where. Because it's in ItemTemplate , then it means it's for every item.
<ListView Name="recordList" ItemsSource="{x:Bind _recordingList, TargetNullValue=0}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:Recording">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="Column1" Width="*" />
<ColumnDefinition x:Name="Column2" Width="8*" />
<ColumnDefinition x:Name="Column3" Width="*" />
</Grid.ColumnDefinitions>
<TextBlock
Name="TextBlock_Time"
Grid.Column="0"
Margin="20"
Foreground="Red"
Text="{x:Bind Time}" />
<TextBlock
Name="TextBlock_Message"
Grid.Column="1"
Margin="20"
Foreground="Green"
Text="{x:Bind Message}" />
<TextBlock
Name="TextBlock_Type"
Grid.Column="2"
Margin="20"
Foreground="LightBlue"
Text="{x:Bind Type}" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
That should make your items look like this.
Check out documentation, as it's explaining it nicely. There are templates in templates. So you can template a Container (how it should display items), and Items (how every item should look like).
Templates
Remember about HorizontalAlignment="Stretch" etc. as this means that the textblock (or Grid) will occupy all of it's space available (horizontally). Tinker with it and you'll get a grasp on how it works.

Context Menu Command not Working

I'm working on a Windows Phone 8 app and I have some problems with a ContextMenu of a List Box. I use the toolkit ContextMenu in the ListBoxItemTemplate as follow:
<DataTemplate x:Key="ListBoxItemTemplate">
<Grid Height="50" Background="#11414141"
Margin="0,1,0,1">
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu>
<toolkit:MenuItem Header="Remove Transaction" Command="{Binding DataContext.RemoveTappedElementCommand}" CommandParameter="{Binding}"/>
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="180"/>
</Grid.ColumnDefinitions>
<!--<StackPanel Grid.Column="0" Background="{Binding IsIncome, Converter={StaticResource TypeToColorConverter}}"/>-->
<StackPanel Grid.Column="0" Background="#FFFB7C26"/>
<TextBlock Grid.Column="1"
Text="{Binding Date, StringFormat=dd/MM}"
VerticalAlignment="Center"
Margin="6,0,6,0"/>
<TextBlock Grid.Column="2"
Text="{Binding Capitolo}"
TextTrimming="WordEllipsis"
VerticalAlignment="Center"/>
<Grid Grid.Column="3">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="15"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Amount, StringFormat=C}"
Grid.Column="0"
Foreground="{Binding IsIncome, Converter={StaticResource TypeToColorConverter}}"
VerticalAlignment="Center"
HorizontalAlignment="Right"
FontSize="25"
FontWeight="SemiBold"
Margin="4,0,4,0"/>
<TextBlock Text="{Binding IsIncome, Converter={StaticResource TypeToSignStringConverter}}"
Grid.Column="1"
Foreground="{Binding IsIncome, Converter={StaticResource TypeToColorConverter}}"
VerticalAlignment="Center"
HorizontalAlignment="Center"
FontSize="25"
FontWeight="SemiBold"/>
</Grid>
</Grid>
</DataTemplate>
I'm using MVVM pattern, so I tried to bind Command propery of the MenuItem to an ICommand of the ViewModel. But when I click on the MenuItem of the context menu, nothing happens, the command is not fired and I can't figure out the reason. Any help will be very appreciated.
There is a problem in your binding:
Command="{Binding DataContext.RemoveTappedElementCommand}"
This will not look for the RemoveTappedElementCommand on the top-level DataContext, but will instead look for the property DataContext on your item view model.
To realy bind to the DataContext of the Page/Control contatining the ListBox, give that item a name
x:Name="Root"
and expand your binding:
Command="{Binding ElementName=Root, Path=DataContext.RemoveTappedElementCommand}"

How to align images to the right and text to the left?

I'm trying to set my layout to appear as follows:
Using the following XAML:
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Name="txtSiteName" VerticalAlignment="Top" Width="auto"/>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" Grid.Column="1" HorizontalAlignment="Right">
<tabs:TabItem Name="tabSettings" TabItemText="Settings"
TabItemImage="settings.png" Margin="5" />
<tabs:TabItem Name="tabDelete" TabItemText="Delete Site"
TabItemImage="delete.png" Margin="5" />
</StackPanel>
</Grid>
However, it's appearing as:
What do I need to do to get the images to align to the right, and have the text vertically aligned on the left?
Try This
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Name="txtSiteName" VerticalAlignment="Top" Width="auto"/>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" Grid.Column="2" HorizontalAlignment="Right">
<tabs:TabItem Name="tabSettings" TabItemText="Settings"
TabItemImage="settings.png" Margin="5" />
<tabs:TabItem Name="tabDelete" TabItemText="Delete Site"
TabItemImage="delete.png" Margin="5" />
</StackPanel>
</Grid>
A parent container isn't stretching to fill the available space.
You can try
<Grid HorizontalAlignment="Stretch" >
<!-- etc -->
and, if that doesn't work, move up the tree until you find the element that's not stretching.
OP Edit in support of the correct answer:
It turns out this is correct - A parent container wasn't stretching to fill the space.
The parent container was the ListBox that I was inserting the items into.
Where before I had just this:
<ListBox Name="SiteListBox" Grid.Row="2" />
I changed it to the following to force the containing ListBoxItems to stretch:
<ListBox Name="SiteListBox" Grid.Row="2">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
Change the TextBlock's Vertical Alignment to Center.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Name="txtSiteName" VerticalAlignment="Center"/>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" Grid.Column="1" HorizontalAlignment="Right">
<tabs:TabItem Name="tabSettings" TabItemText="Settings"
TabItemImage="settings.png" Margin="5" />
<tabs:TabItem Name="tabDelete" TabItemText="Delete Site"
TabItemImage="delete.png" Margin="5" />
</StackPanel>
</Grid>
And try switching your column definitions.

How to insert ListBox into Grid?

I want something like this:
image
And I try to use ListBox:
<ListBox Name="lapsListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Grid.Column="2" Margin="10,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding number}" />
<TextBlock Grid.Column="1" Text="{Binding time}" HorizontalAlignment="Right" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
But I can't align elements. How can I do it by another way?
Try this:
<ListBox Name="lapsListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="10,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50*" />
<ColumnDefinition Width="50*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding number}" HorizontalAlignment="Left"/>
<TextBlock Grid.Column="1" Text="{Binding time}" HorizontalAlignment="Right" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Remove the Grid.Column="2" from the Grid.
Place HorizontalAlignment of Left in the first column Textblock
I modified the Widths of the Columns to be "50%" each.