ScrollViewer not working with ItemsControl - c#

I'm trying to use a ScrollViewer to be able to scroll the items in an ItemsControl but for some reason, it's not working. The scroll view shows but it is disabled.
<UserControl x:Class="Tool.Views.ShortcutsView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignWidth="500"
mc:Ignorable="d" Height="541">
<UserControl.Resources>
<Style x:Key="GlobalShortcutButtonTemplate" TargetType="{x:Type Button}">
<!-- Style code -->
</Style>
</UserControl.Resources>
<Grid Margin="10,40,10,0" Background="White" Height="108" VerticalAlignment="Top">
<ScrollViewer CanContentScroll="True">
<ItemsControl
ItemsSource="{Binding ShortcutsObservableCollection}"
Height="108" VerticalAlignment="Top" HorizontalAlignment="Left">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="10"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button
Height="35"
Content="{Binding ShortcutName}"
Command="{Binding ShortcutCommand}"
CommandParameter="{Binding FilePath}"
Margin="10 0 0 10"
Background="#FF30CCFF"
Foreground="White"
Padding="10,0"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
</UserControl>
This is what I see...
There are plenty of items in the ItemsControl for the scroller to show and be able to scroll the items in it, the rest of the items are hidden.
Any idea what can I do to make the scroller to show up properly?

Just remove Height="108" from your ItemsControl. You can't scroll because there is nothing to scroll.

Related

Grouping issue in Virtualizing Wrap Panel

I am displaying around 1000+ images in my WPF application. All these images are grouped using "GroupID" property. Since I have to take care of memory ,I have used VirtualizingStackPanel and secondly I am using WrapPanel to display all these images as per space accumulated by my ListView.
My solution works fine for small set of images and WPF wrap panel removes the Virtualization effect when items are grouped. Thus i googled this problem and found out we can use VirtualWrapPanel.
I tried it but i started to get Exception
"_owner was null." at VirtualWrapPanel
"_owner.InvalidateScrollInfo();"
MainWindow.cs
List<SearchData> myData = new List<SearchData>();
GetData(ref myData);
listView.ItemsSource = myData;
//Grouping code
CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(myData);
PropertyGroupDescription groupDescription = new PropertyGroupDescription("GroupId");
view.GroupDescriptions.Add(groupDescription);
MainWindow.cs
<Window x:Class="WpfItemVirtualization.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfItemVirtualization"
xmlns:dz="clr-namespace:DevZest.Windows.DataVirtualization;assembly=DevZest.DataVirtualization"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="ListViewItem">
<Setter Property="dz:VirtualListItemBase.AutoLoad" Value="true" />
</Style>
<DataTemplate x:Key="ThumbGridTemplate" >
<VirtualizingStackPanel x:Name="OuterStackPanel" Height="253" Width="230" Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center" Background="White">
<VirtualizingStackPanel x:Name="InnerStackPanel" Height="{Binding Height, ElementName=OuterStackPanel}" Width="{Binding Width, ElementName=OuterStackPanel}" >
<Grid Margin="0,0,0,0" Height="253" Background="#FFCDCDCD">
<TextBlock TextTrimming="CharacterEllipsis" Text="{Binding FilePath}" FontFamily="Segoe UI" Foreground="Black" HorizontalAlignment="Left" TextAlignment="Left" Margin="0" FontSize="12" Height="20" Background="{x:Null}" Width="Auto" VerticalAlignment="Top"/>
</Grid>
</VirtualizingStackPanel>
</VirtualizingStackPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<ListView x:Name="listView"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingPanel.IsVirtualizingWhenGrouping="True"
VirtualizingStackPanel.VirtualizationMode="Recycling"
ScrollViewer.IsDeferredScrollingEnabled="True"
dz:GridViewSort.AutoSort="True"
dz:VirtualListLoadingIndicator.IsAttached="False" ItemTemplate="{StaticResource ThumbGridTemplate}"
Margin="0,35,0,0" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Visible">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<local:VirtualizingWrapPanel IsItemsHost="True" Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<Grid Background="#FF3E3E3E" Height="30" Margin="0,1,0,1">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding GroupId, StringFormat={}Duplicate \Group {0}}" Foreground="Black" FontSize="14" FontFamily="Segoe UI Semibold" VerticalAlignment="Center" Margin="20,0,0,0"/>
</Grid>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
</Grid>
Any suggestion will be helpful. Thank you.

Possible to display images in a ListBox with multiple rows

I am trying to get images in a Listbox to display in a certain way.
Listbox now:
How i want:
As you can see i want the scroll bar to be down the side and there to be multiple columns and rows depending on the size of the listbox.
Define WrapPanel as ListBox's ItemsPanel:
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel ></WrapPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
Don't forget to set Width or MaxWidth to the wrap panel. Once max width is reached it will start placing content on new line...
use WrapPanel with Width set to a value. for an example run below code:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525" >
<Window.DataContext>
<local:ParentViewModel />
</Window.DataContext>
<ListBox Height="auto" ItemsSource="{Binding MyList,Mode=TwoWay}">
<ListBox.Style>
<Style TargetType="{x:Type ListBox}">
<Setter Property="ItemTemplate" >
<Setter.Value>
<DataTemplate>
<Button Content="{Binding}" Padding="15,5" Margin="100,40,0,0"
Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBox}},Path=DataContext.RemoveButtonCommand}"
CommandParameter="{Binding}"
/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.Style>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}},Path=ActualWidth}"
>
</WrapPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
You will get both vertical and horizontal scrollbars. both adjusting according to height and width of window with the elements in listbox. (please bind your own listbox source)

Overlapping Items in WPF ItemsControl

I am having a problem with DataTemplates used in a WPF ItemsControl. I want to be able to "bring forward" any of the items in the list so that they are on top of everything else in the list, but haven't had any luck.
Here's a simple example that illustrates the problem. What I want to see is achieved in the example using a WrapPanel and a bunch of colored blocks:
The first block overlaps the second. Good. When I try to do the same thing with the ItemsControl, the first block falls underneath the second, despite its ZIndex:
How can I make the first block overlap all the others in the ItemsControl?
From my understanding of the ZIndex property, I am assuming that I need to set the ZIndex higher up in the Visual Tree than the Border inside of the DataTemplate, but don't know how or where to do that.
XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:MainViewModel x:Key="mainViewModel" />
<DataTemplate DataType="{x:Type local:FireFighter}">
<Border Background="Pink" Padding="8" Panel.ZIndex="10" Margin="4">
<Border.RenderTransform>
<TranslateTransform X="18" Y="4"/>
</Border.RenderTransform>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FirstName}"/>
</StackPanel>
</Border>
</DataTemplate>
<DataTemplate DataType="{x:Type local:PoliceOfficer}">
<Border Background="Orange" Padding="8" Margin="4">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FirstName}"/>
</StackPanel>
</Border>
</DataTemplate>
</Window.Resources>
<StackPanel>
<ItemsControl DataContext="{StaticResource mainViewModel}"
ItemsSource="{Binding People}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<WrapPanel Margin="0,10,0,0">
<Border Background="Blue" Width="30" Height="30" Margin="4" Panel.ZIndex="10">
<Border.RenderTransform>
<TranslateTransform X="18" Y="4"/>
</Border.RenderTransform>
</Border>
<Border Background="Green" Width="30" Height="30" Margin="4"/>
<Border Background="Green" Width="30" Height="30" Margin="4"/>
</WrapPanel>
</StackPanel>
I found an answer that will work for my situation right here:
https://stackoverflow.com/a/9687758/4912801
It turns out that setting the Panel.ZIndex property wasn't working because WPF inserts a ContentPresenter element for each item in the ItemsControl. In my application, I was trying to get whatever element the mouse is hovering over to come to the front, so applying a style to all ContentPresenters in the ItemsControl allowed me to bring them to the front when the mouse was over them.
I was looking for something similar and this is what did it for me. Use a UniformGrid as your ItemsPanelTemplate, then change the margins on your DataTemplate to overlap as much as you want.
<Grid Grid.Row="1"
Grid.ColumnSpan="2">
<Grid.Resources>
<local:PointsToPathConverter x:Key="pointsToPathConverter"/>
</Grid.Resources>
<Image
Source="{Binding Bmp}"
Stretch="Fill"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" />
<ItemsControl ItemsSource="{Binding AllTraceLines}"
VerticalAlignment="Stretch"
>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="1"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Path Margin="0,-20,0,-20" Data="{Binding Converter={StaticResource pointsToPathConverter}}" Stroke="Red" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Stretch="Fill"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>

WPF - WrapPanel doesn't update/redraw images content

I am loading images from a folder, showing them in a wrappanel in a windows 'Large Icons'-kind of way, so the user can choose/mark which images he would like.
Currently I am reading the image filelocations, add them to a list of strings, and sets the ItemSource to an ItemsControl which looks like this:
<ItemsControl x:Name="ItemsControlPhotos" Margin="10" >
<ItemsControl.Template>
<ControlTemplate>
<WrapPanel FlowDirection="LeftToRight" IsItemsHost="true">
</WrapPanel>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemTemplate>
<DataTemplate >
<Image Source="{Binding}" Width="100" Height="100" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
That seems to work fine. But some of the images looks wierd, it is as if they are only drawn once.
Please refer to this video for an example.
I´ve tried to manually update the list with several different approaches:
ItemsControlPhotos.Items.Refresh();
ItemsControlPhotos.InvalidateArrange();
ItemsControlPhotos.InvalidateMeasure();
ItemsControlPhotos.InvalidateVisual();
But none of it has any effect, so I´m kind of lost.
Thank you very much for your help! :)
EDIT:
This is the full window markup:
<Window x:Class="Name.Space"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:System="clr-namespace:System;assembly=mscorlib"
Title="PhotoChooser"
WindowState="Maximized"
Width="1280"
>
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Styles/Styles.xaml" />
</ResourceDictionary.MergedDictionaries>
<System:Double x:Key="{x:Static SystemParameters.VerticalScrollBarWidthKey}">40</System:Double>
</ResourceDictionary>
</Window.Resources>
<Border BorderBrush="Black" BorderThickness="1" Background="White" Width="1280">
<DockPanel>
<Image Source="..\Images\BGTop.png" DockPanel.Dock="Top" Grid.Row="0" />
<Grid DockPanel.Dock="Top" Margin="0,-80,0,0" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ScrollViewer>
<ItemsControl x:Name="ItemsControlPhotos" Margin="10" >
<ItemsControl.Template>
<ControlTemplate>
<WrapPanel FlowDirection="LeftToRight" IsItemsHost="true">
</WrapPanel>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemTemplate>
<DataTemplate >
<Image Source="{Binding}" Width="100" Height="100" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
<Grid DockPanel.Dock="Bottom">
<Button Height="50" Width="200" Click="ButtonBase_OnClick">Add photos</Button>
<Image Source="..\Images\BGBottom.png" Grid.Row="99" VerticalAlignment="Bottom" Margin="0,0,0,0" />
</Grid>
</DockPanel>
</Border>
</Window>
I´ve didnt really figure the problem out, but I found a solution while working with the project.
Instead of loading the whole image, I would like to only load a thumbnail, to speed up the process. So I followed this link: http://blogs.msdn.com/b/dditweb/archive/2007/08/22/speeding-up-image-loading-in-wpf-using-thumbnails.aspx
And now the problem is gone.
Thank you for your contribution! :)

Problem setting HorizontalAligment="Stretch" in ListBox's DataTemplate

I want my items in listBox to stretch horizontally, but if item's content is bigger than listbox then horizontal scrollbar appears. How to avoid this?
Xaml:
<Window x:Class="WpfApplication6.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate x:Key="testTemplate">
<Border x:Name="border"
BorderBrush="Black"
BorderThickness="1"
Margin="2"
Padding="2"
HorizontalAlignment="Stretch">
<TextBlock Text="{Binding}" />
</Border>
</DataTemplate>
</Window.Resources>
<Grid>
<ListBox x:Name="listBox"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
ItemTemplate="{StaticResource testTemplate}" />
</Grid>
</Window>
Set ScrollViewer.HorizontalScrollBarVisibility to Disabled:
<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled">
...
</ListBox>

Categories