I'm working on UWP with ListView and I'm struggling to implement some basic features.
I have a horizontal ListView with items which need to have variable width. And the width needs to be dynamical, because I want to expand it or retract it based on it's content. To be precise, each item has a number of rectangles inside a StackPanel, I want to be able to add more rectangles, and I would expect the width of the item to increase exponentially.
Right now, the items seem the have equal and locked size. If I increase the content of an item, the other items have the same increased width.
I'm new to UWP, and I can't figure out how to implement such a feature.
<ListView Name="Grid"
Grid.Row="0"
HorizontalAlignment="Stretch"
BorderThickness="0"
ItemsSource="{x:Bind Items, Mode=TwoWay}"
ItemTemplateSelector="{StaticResource TemplateSelector}"
ScrollViewer.HorizontalScrollMode="Enabled"
ScrollViewer.VerticalScrollMode="Disabled"
ScrollViewer.HorizontalScrollBarVisibility="Hidden"
IsItemClickEnabled="True"
CanDragItems = "False"
CanDrag = "False"
CanReorderItems = "False"
AllowDrop = "False"
ItemClick="Grid_ItemClick"
SelectionChanged="Grid_SelectionChanged"
SelectionMode="Single">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid VerticalAlignment="Stretch" HorizontalAlignment="Left"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Padding" Value="0"/>
<Setter Property="Margin" Value="0"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="HorizontalAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
You'll want to change your ItemsPanel to be an ItemsStackPanel with Orientation set to Horizontal. Here's a quick sample:
XAML
<ListView Height="100"
extensions:ListViewExtensions.AlternateColor="Red"
ItemsSource="{x:Bind Items}"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollMode="Auto"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollMode="Disabled">
<ListView.ItemTemplate>
<DataTemplate>
<Grid Width="{Binding Width}">
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsStackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
Code
Items = new ObservableCollection<Item>();
for (int i = 0; i < 20; i++)
{
Items.Add(new Item { Index = i, Width = i * 10 });
}
And you can see that each item has a wider width
That is hardly possible with ListView. Maybe ItemRepeater is control for you. Or you can use StackPanel (with horizontal orientation) inside ScrollViewer.
Related
When I use ScrollIntoView for my listview, The page goes blank for a moment and then rerenders, how can I make this more smooth?
Here is my current code:
<ListView Name="MessageList" Margin="0,82,0,45"
SelectionMode="None"
IsItemClickEnabled="True"
ItemClick="FileMessage_Click"
HorizontalAlignment="Stretch"
ItemTemplateSelector="{StaticResource MsgDataTemplateSelector}"
ItemsSource="{x:Bind messages}" >
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListView.ItemContainerStyle>
</ListView>
And in the code-behind I have this each time a new message is added to the observable collection that feeds into the listview:
MessageList?.ScrollIntoView(MessageList.Items[MessageList.Items.Count -1]);
I didn't reproduced your problem completely. On my PC, this problem only occurs at the first time I add item to ListView. ListView use ItemsStackPanel as its default panel, which supports UI Virtualization. After changing the default panel to StackPanel which has no support for UI Virtualization, the problem doesn't appear.
You can change the ItemsPanel of ListView like below:
<ListView Name="MessageList" Margin="0,82,0,45"
SelectionMode="None"
Height="300"
IsItemClickEnabled="True"
HorizontalAlignment="Stretch"
ItemsSource="{x:Bind messages}" >
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel></StackPanel>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListView.ItemContainerStyle>
</ListView>
Update: To scroll to the last Item, you need to set the height of ListView and call ListView.UpdateLayout before ScrollIntoView:
MessageList.UpdateLayout();
MessageList.ScrollIntoView(MessageList.Items[MessageList.Items.Count - 1]);
My listboxes are data driven from Lists of objects with databinding using a DataTemplate eg:
<ListBox x:Name="TheMainListBox"
ScrollViewer.IsVerticalRailEnabled="True"
ScrollViewer.IsHorizontalRailEnabled="False"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Height="540"
ItemsSource="{Binding}"
Width="Auto"
Margin="0"
Padding="0"
Background="Yellow"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Auto"
SelectionChanged="TheMainListBox_SelectionChanged"
DoubleTapped="TheMainListBox_DoubleTapped"
>
The template:
<ListBox.ItemTemplate>
<DataTemplate>
<Grid or Stackpanel Background="Blue"
Padding="0"
BorderBrush="Black"
BorderThickness="1"
Margin="0"
>
.... Binding Textboxes/blocks
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
I end up with a yellow container, the ListBox, .. with blue rectangles inside, the ListBox items but there is a vertical gap between them. I can set a negative vertical-top margin but that is cruddy and doesn't work for the top item. How can I reduce the vertical gap between items to zero.
If a create a ListBox with static items, each in a ListBoxItem container, eg:
<ListBoxItem BorderThickness="1" Width="100" Height="50"
BorderBrush="Black" Background="Red"/>
It all works as required.
So how can I get rid of the vertical spacing between items with the ItemTemplate/DataBinding?
This is mission critical, thx in advance.
I don't have time to load up a proj to test but you should be able to just kill the margin/padding that could cause it. So add;
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Padding" Value="0"/>
<Setter Property="Margin" Value="0"/>
</Style>
</ListBox.ItemContainerStyle>
I haven't thought a lot of why this could be happening, haven't digged into styles ither, and my answer doesn't look nice, but try Margin="0,-2,0,-2"
<DataTemplate>
<Grid or Stackpanel Background="Blue"
Padding="0"
BorderBrush="Black"
BorderThickness="1"
Margin="0,-2,0,-2"
>
.... Binding Textboxes/blocks
</Grid>
</DataTemplate>
properly setting the height of the ListBoxItem will solve the issue. Here is the code snippet
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Height" Value="Your_Desired_Height"/>
</Style>
</ListBox.ItemContainerStyle>
For listbox please use Height property and for listview use MinHeight property. Replace the required height value in the Your_Desired_Height placeholder.
I coded a list that has as an Itemsource an Observable Collection, which is of type Grids. So the listview is containing 4 Items (Grids). I want the Grids to be like horizontal next to each other, so I tried this in Xaml.
<StackPanel Orientation="Horizontal">
<ListView ScrollViewer.HorizontalScrollBarVisibility="Visible" ScrollViewer.HorizontalScrollMode="Enabled" ItemsSource="{Binding DropGrids, Source={StaticResource view}}" Height="100" x:Name="DropList" RenderTransformOrigin="0.5,0.5" >
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"></StackPanel>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
<AppBarButton Icon="MapPin" Label="Go!" HorizontalAlignment="Right"></AppBarButton>
</StackPanel>
But when I try scrolling the list to the left it is instantly going back (If you want to simulate is use WGA resolution 4 Inch Emulator) and I can't see the fourth Grid on the screen. How do I fix this?
The ListView.ItemsPanel property I got from this post:
Stackoverflow Post - Horizontal Mode
Not sure on the Grid part in your ListView itemsource, but I blogged about how to create a Horizontal ListView here
http://depblog.weblogs.us/2015/03/25/show-items-scrolling-horizontally-with-listview-in-winrt/
I hope this helps...
The complete style is set as
<Style x:Name="BaseListViewStyle" TargetType="ListView">
<Setter Property="ScrollViewer.HorizontalScrollMode" Value="Enabled" />
<Setter Property="ScrollViewer.VerticalScrollMode" Value="Disabled" />
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal"
ScrollViewer.HorizontalScrollMode="Enabled"
ScrollViewer.VerticalScrollMode="Disabled"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
So I made a converter and set up my list box like so:
<ListBox x:Name="QList" Grid.Row="1">
<ListBox.ItemTemplate>
<DataTemplate>
<Border Background="{Binding Status, Converter={StaticResource QColorConverter}}">
<TextBlock Text="{Binding Name}" Foreground="Black" />
</Border>
</DataTemplate>
</ListBox.ItemTemplate >
</ListBox>
However, when I run it, I get just the block right around the text that changes color, not the whole row. How can I make the whole row background change color?
Set ItemContainerStyle HorizontalAlignment to stretch.
<ListBox>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
I have a custom control where I place my SemanticZoom with GridView inside.
The problem is that if GridView has only few items to display then width of the SemanticZoom is less than width of the container. As the result zoom in\out button is placed incorrectly in the middle of the screen.
If there are many items to display, then GridView stretches itself up to the parent control bounds and everything is ok.
How to stretch Semantic zoom (or inner GridView) properly even if there are only few items inside?
Custom container code:
<controls:DataLoader Grid.RowSpan="2" >
<controls:DataLoader.DataContent>
<SemanticZoom x:Name="SemanticZoom" Style="{StaticResource SemanticZoomStyle}" Margin="0,0,0,0" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch">
<SemanticZoom.ZoomedOutView>
..skipped..
</SemanticZoom.ZoomedOutView>
<SemanticZoom.ZoomedInView>
<GridView x:Name="ZoomedInView"
ItemsSource="{Binding Source={StaticResource GroupedPatients}}"
ItemTemplate="{StaticResource PatientItemTemplate}"
Style="{StaticResource DataGridViewStyle}"
behaviors:SelectionChangedCommandBehavior.Command="{Binding SelectPatientCommand}" Margin="0,0,0,0"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"
Background="Yellow">
<GridView.GroupStyle>
<GroupStyle HeaderTemplate="{StaticResource PatientItemGroupHeaderTemplate}">
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid Orientation="Vertical"/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</GridView.GroupStyle>
</GridView>
</SemanticZoom.ZoomedInView>
</SemanticZoom>
</controls:DataLoader.DataContent>
GridView style:
<Style x:Key="DataGridViewStyle" TargetType="GridView">
<Setter Property="IsItemClickEnabled" Value="True"/>
<Setter Property="SelectionMode" Value="None"/>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="Width" Value="Auto"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Margin" Value="0"/>
</Style>
</controls:DataLoader>
The correct solution is to use Grid instead of GridView