I'm looking for the exact solution used by the stock Photo app in Windows 10 to display a list of photos where the dimensions are different. Basically the height of the row are fixed but the width of each element is variable, determined by its relative dimension. A solution I used before was to use WrapPanel as the ItemsPanelTemplate. But using that means I lose the UI virtualisation for a very long list. There is certainly a solution used by Microsoft for the Photo app but I can't find it anywhere.
You can use WrapPanel from XAML Toolkit in your UWP application.
Or you can try to do it this way:
<GridView ItemsSource="{Binding}">
<GridView.ItemTemplate>
<DataTemplate>
<Grid Width="100">
<Image Width="100" Height="50" Source="{Binding somesource}" />
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid MaximumRowsOrColumns="8" Orientation="Horizontal" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
Or you can also use VariableSizedWrapGrid (it will let you to have images with different height)
Related
I am using a WPF UniformGrid to bind alist of items and the xaml is like this
<ListBox Name="lviewSearch" ItemsSource="{Binding SearchSettingsCollection}" SelectionMode="Multiple">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="2"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<ItemsControl Margin="3" Padding="5">
<DockPanel>
<Label Content="{Binding Label}" HorizontalAlignment="Stretch" Cursor="Hand" />
</DockPanel>
</ItemsControl>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
But if the no of items is less then the spacing between rows is too much like this
http://i.stack.imgur.com/Xr5qy.png
How can i ireduce thi s?
Like people said, your UniformGrid has too much vertical space so it expands the rows to take up all that space (stretches).
What you need to do is prevent this default behavior of stretching by setting
VerticalAlignment="Top"
The whole point of the UniformGrid is that the size of cells is uniform and therefore the same size. If you only have a small number of rows compared to the vertical space then each row is going to be pretty tall. Conversely if you have many rows and little vertical space then each row becomes tiny. If this is not an appropriate appearance then you need to use a different method of laying out.
Without knowing much more about the visual design it becomes impossible to recommend a possible alternative. Is the ListBox always the same size or will it vary in height? Does the number of displayed results vary or stay constant? All these change how you might achieve the required result.
One simple solution is to use grid outside Listbox. Set row height as auto. Now Uniform grid will take minimum space as required.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListBox Name="lviewSearch" ItemsSource="{Binding SearchSettingsCollection}" SelectionMode="Multiple">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="2"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<ItemsControl Margin="3" Padding="5">
<DockPanel>
<Label Content="{Binding Label}" HorizontalAlignment="Stretch" Cursor="Hand" />
</DockPanel>
</ItemsControl>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
Is there a general mechanism in WPF that allows for any or almost any control to be selected? For instance, you could have some Image controls on a WrapPanel defined in XAML, and you need to be able to select them either one by one, or by dragging over with the mouse to mark multiple.
In terms of code, I can imagine the following:
<WrapPanel>
<Image Source="{StaticResource ResourceKey=pic1}" />
<Image Source="{StaticResource ResourceKey=pic2}" />
<Image Source="{StaticResource ResourceKey=pic3}" />
<Image Source="{StaticResource ResourceKey=pic4}" />
<Image Source="{StaticResource ResourceKey=pic5}" />
</WrapPanel>
Yes, its called a ListView.
If you need the look of a WrapPanel, just set the ItemsPanel property like so:
<ListView>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
Documentation on MSDN.
You would need to make the Image objects part of the ItemTemplate in your example. You can manually define the Items collection or use a CompositeCollection as the items source as well.
For me it worked with the solution I found here: WrapPanel doesn't wrap in WPF ListView
It's basically the same solution as BradleyDotNET's, but it includes ScrollViewer.HorizontalScrollBarVisibility="Disabled" in the list view and by doing so, it makes the wrap function work without needing to do anything more.
<ListView ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
...
</ListView>
I have problem with my gridview. I'm displaying grouped data in it and using VariableSizedWrapGrid for displaying items. The problem is that every group has the same width equal to the most item. Even if a group contains only 1 item it has width like it was 20 items there. How to make these ItemsPanels have variable width?
My issue is almost the same as described here but when I use VirtualizingStackPanel as GridView.ItemsPanel my VariableSizedWrapGrid is displayed in one row and I need it to be displayed in two rows.
<SemanticZoom.ZoomedInView>
<GridView ScrollViewer.IsHorizontalScrollChainingEnabled="False"
ScrollViewer.IsVerticalScrollChainingEnabled="False"
ItemTemplate="{StaticResource PatientMediaFileBigItemTemplate}"
ItemsSource="{Binding Source={StaticResource PatientVisits} }"
IsItemClickEnabled="True"
SelectionMode="None"
Margin="0,0,0,0" ItemClick="MediaFileIcon_Click"
>
<GridView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<Button Content="{Binding DateOfVisit, Converter={StaticResource StringFormatConverter}, ConverterParameter='{}{0:dd MMM yyyy}'}" FontSize="28" Foreground="Black" BorderThickness="0" Click="ButtonVisit_OnClick"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid Orientation="Vertical" Margin="0,0,80,0" Width="Auto" Background="BlueViolet"/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</GridView.GroupStyle>
</GridView>
</SemanticZoom.ZoomedInView>
You might need to change the ItemsPanel of your GridView to a StackPanel, but note this will limit the number of items you can put in your GridView as it disables virtualization. A better option might be to keep showing a limited number of items in a group, but add a button (really the group header button with a chevron glyph should work) to navigate to a full view of the selected group.
Currently my FlipView allows the user to select multiple pictures from the local Pictures folder and then display the selected images in FlipView. However it will only work if the user selects a small number of pictures. When too many large images are selected, the app crashes. I read that VirtualizingStackPanel stores the 3 images in memory (before, current, after) so that not all of the images are being loaded at once.
This is my FlipView (edited on November 14th).
<FlipView x:Name="flpView" Grid.Row="1" Margin="10, 10, 10, 10">
<FlipView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</FlipView.ItemsPanel>
<FlipView.ItemTemplate>
<DataTemplate>
<Grid>
<Image Source="{Binding}" Stretch="Uniform"/>
</Grid>
</DataTemplate>
</FlipView.ItemTemplate>
</FlipView>
Yes, if you use a VirtualizingStackPanel it will reuse the Ítems, and if you won't have problems with large data collections. Try this:
<FlipView HorizontalAlignment="Left" Height="464" Margin="718,288,0,0" VerticalAlignment="Top" ItemsSource="{Binding YourSource}" ItemTemplate="{StaticResource ImageTemplate}">
<FlipView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel/>
</ItemsPanelTemplate>
</FlipView.ItemsPanel>
</FlipView>
Im a beginner in WPF programming, coming from .NET 2.0 C#.
Im trying to make a horizontal StackPanel which should be filled with data from a table in a database. The problem is that I want it to display an image with some text from the table below and then stack those two items horizontally.
Here's some pseudo-code to display what I want to do:
<StackPanel Orientation="horizontal" ItemsSource="{Binding Path=myTable}">
<StackPanel>
<Image Source="User.png"/>
<Label HorizontalAlignment="Center" Content="{Binding Path=UserName}"></Label>
</StackPanel>
</StackPanel>
I simply cannot figure oout how to do this.
Julien's answer is correct for your written description, however, looking at your XAML, it appears you are looking for something like the following:
<DataTemplate x:Key="UserDataTemplate">
<StackPanel>
<Image Source="User.png"/>
<Label HorizontalAlignment="Center" Content="{Binding Path=UserName}" />
</StackPanel>
</DataTemplate>
<ItemsControl x:Name="UserList" ItemTemplate="{StaticResource UserDataTemplate}" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
You definately need an ItemsControl (or some derivation of) to bind your source to. Then you can change the the orientation by setting it's items panel (which I believe is a VirtualizingStackPanel with Vertical orientation by default) so just set it to a VirtualizingStackPanel with Horizontal Orientation. Then you can set the ItemsTemplate for each of your items to the layout you desire (an image stacked on top of text bound from your database).
Basically, you want to use a control capable of displaying an enumeration of objects. The control capable of this is the class ItemsControl and all of its descendants (Selector, ListBox, ListView, etc).
Bind the ItemsSource property of this control to a list of objects you want, here a list of users you've fetched from the database. Set the ItemTemplate of the control to a DataTemplate that will be used to display each item in the list.
Sample code:
In a Resources section (for example Window.Resources):
<DataTemplate x:Key="UserDataTemplate">
<StackPanel Orientation="Horizontal">
<Image Source="User.png"/>
<Label HorizontalAlignment="Center" Content="{Binding Path=UserName}" />
</StackPanel>
</DataTemplate>
In your Window/Page/UserControl:
<ItemsControl x:Name="UserList" ItemTemplate="{StaticResource UserDataTemplate}" />
In your code behind:
UserList.ItemsSource = ... // here, an enumeration of your Users, fetched from your db