Winrt - Specific ItemTemplate on last item of ListView - c#

I have this list view on a windows store app project
<ListView ItemsSource="{Binding Attachments}" IsItemClickEnabled="False" SelectionMode="None">
<ListView.ItemTemplate>
<DataTemplate >
<Grid Width="280" Height="50" Margin="85,0,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="5" />
</Grid.RowDefinitions>
<RadioButton GroupName="meetingFiles" Content="TESTE" Style="{StaticResource RadioButtonStyle1}"></RadioButton>
<TextBlock Text="1" HorizontalAlignment="Right"></TextBlock>
<Grid x:Name="whiteLine" Grid.Row="1" Width="270" Height="1" Background="White" HorizontalAlignment="Center" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
i want that my last item on the listview dont show the grid named whiteLine
how can i do that? or is it impossible?

An alternative solution would be to add a Listview.footer as so:
<ListView>
<!-- Your Listview ItemTemplate /-->
<ListView.Footer>
<Grid Width="280" Height="50" Margin="85,0,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="5" />
</Grid.RowDefinitions>
<RadioButton GroupName="meetingFiles" Content="TESTE" Style="{StaticResource RadioButtonStyle1}"></RadioButton>
<TextBlock Text="1" HorizontalAlignment="Right"></TextBlock>
</ListView.Footer>
</ListView>
This isn't really changing the last item, it is adding an element that is always at the bottom of the ListView, and looks the same as your items. This will give the user the impression that it is part of the listview, and you will keep your code simple.

Either
<ListView ItemTemplateSelector="..."/>
Or binding the Grid's Visibility would do the trick. But you would need some type of flag variable in your Model such that you can use that to determine if it is the last one in the list.
I used the above solution to alternate the background color of each item in the ListView, with my Model containing a RowID as well.

Related

Using an ItemsControl inside of a ListView ItemTemplate with XAML

So, a bit of a crazy request. I need a list of items, which I plan to use a ListView for, but inside each element, I need another "List" so-to-speak that will expand horizontally.
Here is a crude drawing of the basic idea I'm going for:
For my code, this is what I've tried, but it's not working. (And yes, I'm purposely not using binding yet so I can just use the design view to get everything looking right)
<ListView>
<ListView.ItemTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Grid.IsSharedSizeScope="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="KpiColumn0" />
<ColumnDefinition Width="Auto" SharedSizeGroup="KpiColumn1" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<StackPanel Orientation="Vertical" Grid.Row="0" Grid.Column="0">
<TextBlock Text="Test" />
<TextBlock Text="Test" FontSize="8" Margin="0,-4,0,0" />
</StackPanel>
<TextBlock Grid.Row="0" Grid.Column="2" Text="Test" />
<TextBlock Grid.Row="1" Grid.Column="0" Text="Test" />
<TextBlock Grid.Row="1" Grid.Column="2" Text="Test" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.Items>
<MenuItem />
</ListView.Items>
</ListView>
How can I use a ListView to hold a list of items in each of its item, that expand horizontally, based on how many elements are in the List that each ListItem is bound to?
Add this to your inner ItemsControl and the items will be shown in horizontal alignment.
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
Note that you won't be able to use the designer view for this. You'll need to remove the ListView.Items that you have, and instead use binding or code-behind to have it show when running.
Something like this should work, if you give the ListView a Name of LV:
LV.ItemsSource = new List<List<int>>
{
new List<int> {1,2,3,4, },
new List<int> {1,2,3,4, }
};

Listview is resizing correctly in Universal App Windows 10

I've got a XAML page which is broken down with a grid as follows:
<Grid Background="Green">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
</Grid>
The first and third row contain a TextBlock each and are set to auto-resize to their height and the ListView is contained in the middle row and it is suppose to stretch within the area.
The ListView appears to be resized based on the number of items rather than the available visible area that should be allocated to the middle row.
This has 2 side effects:
I can't scroll to view the other items
It pushes the TextBlock in the third row out of the screen.
If I set a specific height on the ListView, it works as expected but I want my ListView to use the entire area of the screen between the top and bottom rows.
It displays as expected in the IDE, but no data is loaded but I can clearly see my top and bottom row (in green) and I can see the ListView is stretched between these 2 rows.
I've used this numerous times in the past but with a universal app for Windows 10, so I'm wondering if this is a new behaviour I'm not aware of or is this a bug?
This is full code without the DataTemplate for clarity sake. Just to be clear, my DataTemplate is displaying correctly, but I just can't scroll as there is no scrollbar since the listview is stretched based on the items, rather than being restricted to the available area of the middle row.
<Grid Background="Green">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="Top Row" />
<ListView ItemsSource="{Binding Items}"
Grid.Row="1"
Background="Red">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
....
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<TextBlock Text="bottom row" Grid.Row="2"/>
</Grid>
You need to wrap your ListView in a ScrollView. This will fill the empty area and add a scroll bar as the list overflows the empty area.
I figured out the problem. It isn't a change in behaviour or a bug!
As someone mentioned that they tried to reproduce the problem and couldn't, I decided to do the same.
When I put my grid and ListView directly on the MainPage, I couldn't reproduce it.
When I put my grid and ListView on a sub-page (i.e. GridPage) and loaded it into the frame contained on the MainPage, I couldn't reproduce it
and that's when the penny dropped!!
In my code, I used (for the first time) a SplitView and this SplitView was contained in a grid with 2 rows and stupidly, both rows were set to "Auto" when I should have set the first one to Auto for my hamburger menu, logo and title and the second one should have been set to '*'.
The second I changed my second row to '*', the problem got sorted. It had nothing to do with the Grid Page which contained the grid I originally posted problem with.
<Grid Background="{ThemeResource FocusVisualWhiteStrokeThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
Here is the full code:
<Grid Background="{ThemeResource FocusVisualWhiteStrokeThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Border Background="White"
Grid.Row="0"
Grid.Column="0"
Margin="0,10,0,10">
<ToggleButton Style="{StaticResource SymbolButton}"
Foreground="{ThemeResource ApplicationForegroundThemeBrush}"
FontSize="{ThemeResource ControlContentThemeFontSize}"
Command="{Binding HamburgerCommand}" >
<FontIcon x:Name="Hamburger"
FontFamily="Segoe MDL2 Assets"
Glyph=""
Foreground="#ff6600" />
</ToggleButton>
</Border>
<Border Background="White" Grid.Row="0"
Grid.Column="1" Margin="10,0,0,0">
<Image Stretch="Fill" Source="{Binding SelectedSection,
Converter={StaticResource SectionImageConverter}}"
Height="20" Width="20" />
</Border>
<Border Background="White"
Grid.Row="0"
Grid.Column="2"
Margin="10,0,0,0">
<TextBlock x:Name="Header" Text="{Binding SelectedSection,
Converter={StaticResource
SectionTitleConverter}}"
Style="{StaticResource TagLineTextStyle}"
Foreground="#ff6600"
VerticalAlignment="Center"
Margin="10,0,0,0"/>
</Border>
</Grid>
<SplitView x:Name="Splitter"
IsPaneOpen="{Binding IsPageOpen}"
DisplayMode="Inline"
Grid.Row="1">
<SplitView.Pane>
<ListBox x:Name="SectionControl" SelectionMode="Single"
ItemsSource="{Binding Sections}"
HorizontalAlignment="Left"
Background="White"
BorderThickness="0"
VerticalAlignment="Top"
SelectedItem="{Binding
SelectedSection, Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Converter={StaticResource
SectionImageConverter}}"
Height="17" Width="17"/>
<TextBlock Text="{Binding
Converter={StaticResource
SectionTitleConverter}}"
Margin="20,0,0,0"
Foreground="#ff6600" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="SelectionChanged">
<Core:InvokeCommandAction Command="{Binding
ItemClickCommand}"
CommandParameter="{Binding SelectedSection}" />
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</ListBox>
</SplitView.Pane>
<SplitView.Content>
<Frame x:Name="SectionFrame"/>
</SplitView.Content>
</SplitView>
</Grid>
Thanks again for the feedback/help. Much appreciated!

WP8.1 Popup - Slow to render

I made a popup control that can accept any view of type FrameworkElement. In addition, you can provide a view model, which will be bound to the DataContext of the child view being provided. Everything works, but it takes a couple of seconds to render the data. The view model has an ObservableCollection that contains about 300 items. So in all honesty, 300 items shouldn't cause any issues.
There is no lag what so ever, If I extract the xaml from the popup to a regular page.
So, is there something inside a Popup control that happens when it's Child content property is being set, that would cause such a delay? Because this is blowing my mind at the moment.
Thanks in advance!
[Update]
As requested, the XAML that forms the child content of the tool window:
<UserControl
x:Class="App.Controls.ContactSelector"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
mc:Ignorable="d" x:Name="contactSelector"
DataContext="{Binding ContactSelectorViewModel,Source={StaticResource Locator}}">
<Grid HorizontalAlignment="Stretch" Style="{StaticResource BaseGridStyle}">
<Grid.RowDefinitions>
<RowDefinition Height="1*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ListView Grid.Row="0" ItemsSource="{Binding ContactCollection}">
<ListView.ItemTemplate>
<DataTemplate>
<Grid Margin="12">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<!--<Image Margin="0,0,10,0" Grid.Row="0" Grid.Column="0"
Source="{Binding Thumbnail}" MaxHeight="35"
Visibility="{Binding Thumbnail, Converter={StaticResource ObjectNullToVisibilityConverter}}" />-->
<!--<Image Margin="0,5,5,5" Grid.Row="0" Grid.Column="0" MaxHeight="35"
Source="ms-appx:///Assets/Images/Contact.png"
Visibility="{Binding Thumbnail, Converter={StaticResource InverseObjectNullToVisibilityConverter}}" />-->
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding FullName}"
VerticalAlignment="Center"
Style="{StaticResource TextBlockMedium}" />
<!--<Grid Grid.Row="1" Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ItemsControl Grid.Row="0" ItemsSource="{Binding MobileNumbers}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="10,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Margin="0"
Text="{Binding Number}"
HorizontalAlignment="Stretch"
Style="{StaticResource TextBlockMedium}">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Tapped">
<core:InvokeCommandAction
Command="{Binding DataContext.SelectContact, ElementName=contactSelector}"
CommandParameter="{Binding}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</TextBlock>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>-->
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
<!--<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<Border>
<TextBlock Text="{Binding Key}"
VerticalAlignment="Center" HorizontalAlignment="Center"
Style="{StaticResource TextBlockMedium}"
Padding="5" Margin="5" FontWeight="SemiBold" />
</Border>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>-->
</ListView>
</Grid>
</UserControl>
So I have commented out the entire section of the ItemsControl, but this did not solve the problem. When the Popup opens, it still takes quite a while to show the containing items.
It isn't slow when it's scrolling, it's slow in rendering the initial items.
The problem is in the ItemsControl which displays the MobileNumbers collection. You should not have an ItemsControl as an ItemTemplate for another ItemsControl (in your case, the ListView). You can do that only when you display small amount of items.
Because of this your MobileNumbers items are not virtualized and this is where the performance problem comes from, as all the items need to be displayed to render the item template.
You can try creating a flat list of objects, and then use ItemTemplateSelector to display different item templates for different types. For example you could have the following ObservableCollection as the ItemsSource:
Header
Contact info
Mobile number1
Mobile number2
Header
Contact info
Mobile number
etc.

Setting visiblity to section of data template in a listview

I have a WPF/MVVM application. When a item is selected in my listview I have a section of the datatemplate I want to be visible, then when a different item is selected it will be collapsed, and the new item will be visible. I will mock up some code below to help show what I am trying to do.
My question is how to do this for just the selected item staying in the bounds of mvvm. I know I can bind to a property in my viewmodel, but if every item has the same binding they all open, I need it to be for just the selected item and I'm not sure the best way to deal with this in MVVM, looking for suggestions. The item source in my listview is a ObservableCollection of a class that stores some default data I need when the item is selected.
<ListView Name="lvMain"
ItemsSource="{Binding MyItemSource, Mode=TwoWay}"
SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding MyPath, Mode=TwoWay}" />
<!-- removing the rest to keep this short -->
</Grid>
<!-- This section below is collapsed by default, when selected I'd like to set the visibility, my question is how to only set the visibility in the grid below when the item is selected -->
<Grid Grid.Row="1" Visibility="{Binding ??}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- removing the rest to keep this short -->
</Grid>
</Grid>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
First you'll need some boolean to visibility converter but you can use built in one if you don't have yours and then you need to use RelativeSource binding to go up the visual tree, find ListViewItem and bind to its IsSelected property via that converter
<ListView Name="lvMain" ...>
<ListView.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</ListView.Resources>
<ListView.ItemTemplate>
<DataTemplate>
<!-- removed content -->
<Grid
...
Visibility="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListViewItem}},
Path=IsSelected,
Converter={StaticResource BooleanToVisibilityConverter}}">
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

bind the data to list picker using code behind

i have a user control, in that i am having one list picker.
code is :
<Grid x:Name="LayoutRoot" Background="{StaticResource PhoneChromeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<toolkit:ListPicker x:Name="lstPicker" Grid.Row="1" Margin="25,0,25,15" />
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Center" >
<Button Width="200" x:Name="btnReAssign" Content="reassign" Margin="5"/>
<Button Width="200" x:Name="btnCancel" Content="cancel" Margin="5"/>
</StackPanel>
</Grid>
Now i m creating the pop up user control at run time.
MyTaskPopupWindow myTaskPopUpWindow = new MyTaskPopupWindow();
this contains the list picker.
Now i am binding this listpicker with my data object.
myTaskPopUpWindow.lstPicker.ItemsSource = GetRegisterUserOC;
but class name is displaying in the list picker, not the property. i am not getting how should i bind the one of the property to this list picker. Can i bind one of the property from code behind, as i dont want to make changes in user control.
Typically you do something like this:
<toolkit:ListPicker x:Name="lstPicker" Grid.Row="1" Margin="25,0,25,15" >
<toolkit:ListPicker.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding YourDisplayPropertyOnObject}"/>
</DataTemplate>
</toolkit:ListPicker.ItemTemplate>
</toolkit:ListPicker>
If you would rather take a lazier approach, you can simply override the ToString() property on the object you are binding to display how you would like.
I never used ListPicker, but can't you set the DisplayMemberPath to the property you want to show (eg. Name)?
<Grid x:Name="LayoutRoot" Background="{StaticResource PhoneChromeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<TextBlock x:Name="tbkTitle" Margin="25,25,25,15" FontSize="32" />
<toolkit:ListPicker x:Name="lstPicker" Grid.Row="1" Margin="25,0,25,15" DisplayMemberPath="Property" />
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Center" >
<Button Width="200" x:Name="btnReAssign" Content="reassign" Margin="5"/>
<Button Width="200" x:Name="btnCancel" Content="cancel" Margin="5"/>
</StackPanel>
</Grid>
Or
myTaskPopUpWindow.lstPicker.DisplayMemberPath = PropertyName;

Categories

Resources