I'd like to create a list in WPF that displays data in several columns, like Explorer display a list of files in 'Small icons' view mode:
Each item must be represented by a DataTemplate and the scrolling is supposed to be horizontal. How do I make such a list?
You need to change ItemsPanel of your ListBox to WrapPanel with vertical Orientation and disable vertical scroll bar on your ListBox
Something like this:
<ListBox ScrollViewer.VerticalScrollBarVisibility="Disabled" ItemsSource="{Binding=MyItems}">
<ListBox.ItemTemplate>
<DataTemplate>
<!--my item template-->
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
try something like below.
<ListBox>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="3"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<DataTemplate>
<!--my item template-->
</DataTemplate>
</ListBox>
can use this link
try something like below.
<ListView ItemsSource="{Binding Files}" >
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Width="{Binding (FrameworkElement.ActualWidth), RelativeSource={RelativeSource AncestorType=ScrollContentPresenter}}"
ItemWidth="{Binding (ListView.View).ItemWidth, RelativeSource={RelativeSource AncestorType=ListView}}"
MinWidth="{Binding ItemWidth, RelativeSource={RelativeSource Self}}"
ItemHeight="{Binding (ListView.View).ItemHeight, RelativeSource={RelativeSource AncestorType=ListView}}" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.View>
<GridView >
<GridView.Columns>
<GridViewColumn DisplayMemberBinding="{Binding Name}" />
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
code behind sample.
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
Files = new ObservableCollection<FileInfo>();
var files = new System.IO.DirectoryInfo("C:\\Windows\\").GetFiles();
foreach (var item in files)
{
Files.Add(item);
}
this.DataContext = this;
}
public ObservableCollection<FileInfo> Files { get; set; }
}
Related
I am developing a Windows 10 UWP, and a Windows Phone 8.1 project. In the project, there are tags like in Instagram, which can be seen in the picture. These tags are printed on the screen using a GridView. The problem is that I couldn't make the GridView items' width dynamic by their content. It takes the first item's width and gives all the other items the same width. For the shorter words, it's not a problem but some letters of the longer words are not visible.
Here is a screen shot of the problem.
The code I wrote;
<GridView SelectionMode="None" ItemsSource="{Binding TagsArray}" ScrollViewer.IsHorizontalRailEnabled="True">
<GridView.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock x:Name="tagButton" Tapped="tagButton_Tapped" FontWeight="Medium" Text="{Binding}" Foreground="#063076" FontSize="11" HorizontalAlignment="Left"/>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.ItemContainerStyle>
<Style TargetType="GridViewItem">
<Setter Property="Margin" Value="0,-15,0,-15"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</GridView.ItemContainerStyle>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid Orientation="Horizontal"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
I would recommend you to use WrapPanel from UWP Community Toolkit for this.
You can use it inside the GridView by replacing the ItemsPanel:
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel Orientation="Horizontal" AllowDrop="True">
</toolkit:WrapPanel>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
Here's a full example:
<GridView x:Name="ItemGrid" Width="450" HorizontalAlignment="Left" VerticalAlignment="Bottom">
<GridView.ItemTemplate>
<DataTemplate >
<TextBlock Text="{Binding}"/>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<controls:WrapPanel Orientation="Horizontal" AllowDrop="True">
</controls:WrapPanel>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
When used with the following collection:
var ite = new ObservableCollection<string>();
ite.Add("#tag1");
ite.Add("#a");
ite.Add("#tag3");
ite.Add("#differ");
ite.Add("#tag5");
ite.Add("#longertag");
ite.Add("#verylongtag");
ite.Add("#tag1");
this.ItemGrid.ItemsSource = ite;
Provides the following output:
I have a ListView that uses GridView to display some data. One of the fields contains a list with image paths. Therefore I defin a GridViewColumn and create a DataTemplate. Dis DataTemplate contains another ListView with the Images list as new DataContext. When I don't write anything in the inner StackPanel, I can see that a list of string (in the format AppName.ClassName) is displayed in left to right order.
But whenever I try to display the strings as something else, eg
<Image Source="{Binding Name}" Height="32"/>
I get an System.Windows.Markup.XamlParseException . Even with data binding I get an exception. Eg
<Image Source="Images/Camera_32xLG.png" Height="32"/>
. Any hint, what I might do wrong?
<GridViewColumn Header="Images">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ListView ItemsSource="{Binding Images}" BorderThickness="0">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal">
--> here is where I don't know what to do next
</StackPanel>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
Since the StackPanel is a part of ItemsPanelTemplate, you should just define it's properties and not explicitly add any children. The way to specify appearance of each item is through the ListView.ItemTemplate property:
<ListView ItemsSource="{Binding Images}" BorderThickness="0">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<Image Source="{Binding Name}" Height="32" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
So, I am making a List of UserControl which ViewModel is assigned via ItemsControl
<ItemsControl Grid.Column="0" Grid.Row="1" x:Name="itemsControlStack"
ItemsSource="{Binding ListOfViewModels, Mode=OneWay}" VerticalAlignment="Bottom">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:UserControlA/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Above code works, but I want to show it reversed, without changing the data, so :
<ItemsControl Grid.Column="0" Grid.Row="1" x:Name="itemsControlStack"
ItemsSource="{Binding REVERSEDListOfViewModels, Mode=OneWay}" VerticalAlignment="Bottom">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:UserControlA/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Somewhere in my ViewModel, which I have checked via breakpoint that the code is executed
public ICollectionView REVERSEDListOfViewModels { get; private set; }
REVERSEDListOfViewModels = CollectionViewSource.GetDefaultView(ListOfViewModels);
REVERSEDListOfViewModels.SortDescriptions.Add(new SortDescription("ID", ListSortDirection.Descending));
But it suddenly not working. it doesn't return error anywhere, but UserControlA now don't properly presented. (The user control are presented without its data - which stored on the REVERSEDListOfViewModels)
Any idea why?
I'm adapting this solution to my needs: http://www.abhisheksur.com/2010/08/woring-with-icollectionviewsource-in.html
The XAML part of the listview is:
<ListView Grid.Row="1" Name="lvIcons" ItemsSource="{Binding}">
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Width="{Binding (FrameworkElement.ActualWidth),
RelativeSource={RelativeSource AncestorType=ScrollContentPresenter}}"
ItemWidth="{Binding (ListView.View).ItemWidth,
RelativeSource={RelativeSource AncestorType=ListView}}"
MinWidth="{Binding ItemWidth, RelativeSource={RelativeSource Self}}"
ItemHeight="{Binding (ListView.View).ItemHeight,
RelativeSource={RelativeSource AncestorType=ListView}}" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
I've got a button to control if I want to show grouped or not and the code behind for this button is:
private void btnGroup_Click(object sender, RoutedEventArgs e)
{
this.Source.GroupDescriptions.Clear();
PropertyInfo pinfo = typeof(country_icon).GetProperty(cmbGroups.Text);
if (pinfo != null)
this.Source.GroupDescriptions.Add(new ropertyGroupDescription(pinfo.Name));
}
When grouping is on, the wrappanel is working nicely (i'm grouping by an integer property on the icons)
But when grouping is not on, no wrapping:
I'm not worried about different sizes of icon's - i'll fix that later.
How do I fix wrapping when not grouped ? Is there a different template in use ?
Thanks to the answer of this question WPF ListView with horizontal arrangement of items? to help get me to where I am now.
I'm trying to create DataTemplates for a PropertyCollection (of PropertyDescriptors) to display the items in the collection in this format,
descriptor1 > descriptor2 > descriptor3 > descriptor4 > descriptor5
Each descriptor would be a link (using Hyperlink), my question is can I do this with Labels (which is not an ItemsControl host)? If yes, can anyone give me an example on how to achieve this with DataTemplates?
Also, is there anyway to access the property descriptor from the DataTemplate? For example suppose I want to use the current instance of property descriptor as the CommandParameter.
Appreciate any help, thanks.
you can try to do this with a ListBox with an ItemsPanel that uses a horizontal layout for the items (I'm just binding to a list of strings in my example). HTH.
Code:
public List<string> Properties { get; set; }
XAML:
<ListBox ItemsSource="{Binding Properties}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Width="{Binding (FrameworkElement.ActualWidth), RelativeSource={RelativeSource AncestorType=ScrollContentPresenter}}"
ItemWidth="{Binding (ListView.View).ItemWidth, RelativeSource={RelativeSource AncestorType=ListView}}"
MinWidth="{Binding ItemWidth, RelativeSource={RelativeSource Self}}"
ItemHeight="{Binding (ListView.View).ItemHeight, RelativeSource={RelativeSource AncestorType=ListView}}" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock>
<Hyperlink NavigateUri="{Binding}">
<TextBlock Text="{Binding StringFormat={}{0} >}"/>
</Hyperlink>
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Screenshot: