WPF. Scroll ListBox by item - wpf

I have listbox where are icons and I have to scroll this listbox by item (now it is scrolling by pixel's). I try to use ScrollViewer.CanContentScroll but it does not work. I think it is problem with WrapPanel
ListBox example:
My xaml:
<Style TargetType="ListBox">
<Setter Property="Height" Value="490"/>
<Setter Property="Width" Value="968"/>
<Setter Property="Margin" Value="30,98,362,135"/>
<Setter Property="Padding" Value="5,25,0,27"></Setter>
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Visible"/>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="ListBoxItem">
<Setter Property="BorderThickness" Value="5"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="Margin" Value="3,3,0,0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border x:Name="backgroundBorder" Width="Auto">
<ContentPresenter>
<ContentPresenter.ContentTemplate>
<DataTemplate>
<Grid Width="170" Height="212" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Image Grid.Row="0" Source="{Binding Path=Image}" Stretch="UniformToFill" />
<Label Grid.Row="1" Margin="0,14,0,0" Content="{Binding Path=Title}" HorizontalAlignment="Center"
FontFamily="Arial" FontSize="18" FontWeight="Normal" Foreground="#3F3E3E"/>
</Grid>
</DataTemplate>
</ContentPresenter.ContentTemplate>
</ContentPresenter>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ListBox ItemsSource="{Binding Path=MyImages, ElementName=window1}"
ScrollViewer.CanContentScroll="True"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Visible"/>

Related

How to stylise horizontal contextmenu

I would like to make a contextmenu like the blue one on this image:
I can't figure how to make it so do you have some clues/tutorials/... to share with me?
For now, i'm stuck with this XAML
<Style x:Name="HorizontalContextMenu" TargetType="{x:Type ContextMenu}">
<Setter Property="Background" Value="CadetBlue" />
<Setter Property="BorderBrush" Value="DarkBlue" />
<Setter Property="HorizontalOffset" Value="50"/>
<Setter Property="VerticalOffset" Value="50"/>
<Setter Property="Height" Value="48"/>
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Grid.IsSharedSizeScope" Value="true" />
<Setter Property="HasDropShadow" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContextMenu">
<Border BorderThickness="0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="24"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Path Width="100" Height="100"
Data="{DynamicResource RightArrow}"
Fill="Blue" Stretch="Fill"
Grid.Column="0"/>
<StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Cycle" Grid.Column="1" Orientation="Horizontal"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
After two days of reflection, i finally achieve this solution:
Frontend XAML
<Button x:Name="btnExpressions" Style="{StaticResource MyMenuButton}" Content="Expressions" Tag="{x:Static iconPacks:PackIconMaterialKind.HeartPulse}" Click="BtnExpressions_Click">
<Button.ContextMenu>
<ContextMenu Style="{StaticResource HorizontalContextMenu}">
<MenuItem Name="BtnA" Header="B" Tag="{x:Static iconPacks:PackIconMaterialKind.RunFast}" Style="{StaticResource HMI}"/>
<MenuItem Name="BtnB" Header="F" Tag="{x:Static iconPacks:PackIconMaterialKind.RunFast}" Style="{StaticResource HMI}"/>
<MenuItem Name="BtnC" Header="T" Tag="{x:Static iconPacks:PackIconMaterialKind.RunFast}" Style="{StaticResource HMI}"/>
</ContextMenu>
</Button.ContextMenu>
</Button>
Style XAML
<Style x:Key="HorizontalContextMenu" TargetType="{x:Type ContextMenu}">
<Setter Property="Background" Value="#AF38789E" />
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Height" Value="48"/>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal" Background="Transparent"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContextMenu" >
<Border BorderThickness="0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Path Data="M0,0.5 L1,0.75 1,0.25Z" Margin="0"
Grid.Column="0"
StrokeThickness="0"
Stroke="{TemplateBinding Background}"
Fill="{TemplateBinding Background}"
Stretch="Fill"
Width="10" Height="20"/>
<StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Cycle"Grid.Column="1" Orientation="Horizontal" Background="{TemplateBinding Background}"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="HMI" TargetType="MenuItem">
<Setter Property="Foreground" Value="White"/>
<Setter Property="Opacity" Value="0.5"/>
<Setter Property="Width" Value="48" />
<Setter Property="Height" Value="48" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<Border>
<iconPacks:PackIconMaterial Kind="{Binding Tag, RelativeSource={RelativeSource AncestorType=MenuItem}}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Opacity" Value="1" />
</Trigger>
</Style.Triggers>
</Style>
Code behind (VB.NET version)
Private Sub BtnExpressions_Click(sender As Object, e As RoutedEventArgs)
Dim btn As FrameworkElement = sender
If btn IsNot Nothing Then
btn.ContextMenu.PlacementTarget = btn
btn.ContextMenu.Placement = Primitives.PlacementMode.Right
btn.ContextMenu.HorizontalOffset = -10
btn.ContextMenu.VerticalOffset = 0
btn.ContextMenu.IsOpen = True
End If
End Sub
Hope this helps someone else.

WPF DataGrid ColumnHeaders Scroll Out of Sync with Data Cells

The ColumnHeaders of my WPF DataGrid get out of sync with the data cells when scrolling horizontally. It appears that the Columnheaders scroll faster than the data cells. Vertical scrolling is workig ok. This is the View, which sizes the width of the DataGrid according to the Window size:
<Window.DataContext>
<vm:DemoDgViewModel/>
</Window.DataContext>
<Grid x:Name="dGrid" Height="300" Margin="15,0,15,0" Background="AliceBlue" Width="1000">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="32"/>
<RowDefinition Height="32"/>
<RowDefinition Height="32"/>
<RowDefinition Height="32"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<DataGrid x:Name="demoDG" Width="{Binding Path=Width,
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"
ItemsSource="{Binding Path = DataContext.AppDataLcv,
RelativeSource={RelativeSource FindAncestor, AncestorType=
{x:Type Window}}}" Style ="{DynamicResource StDataGrid2}"
Grid.Row="0" Grid.RowSpan="6" Height="300" AlternationCount ="2"
IsSynchronizedWithCurrentItem="True" SelectionMode ="Single"
AutoGenerateColumns="False" CanUserAddRows="True" CanUserSortColumns ="True"
ScrollViewer.CanContentScroll="True" ColumnWidth="Auto">
<DataGrid.Columns>
<DataGridTextColumn Header="desciption" SortMemberPath="desc"
Binding ="{Binding Path=desc}" IsReadOnly="False" CanUserSort="True"
Width ="200">
<DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Padding" Value="5,0,0,0"/>
</Style>
</DataGridTextColumn.ElementStyle>
<DataGridTextColumn.EditingElementStyle>
<Style TargetType="TextBox">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Padding" Value="5,0,0,0"/>
</Style>
</DataGridTextColumn.EditingElementStyle>
</DataGridTextColumn>
<!-- column 2, 3, 4, 5 same as the first -->
</DataGrid.Columns>
</DataGrid>
</Grid>
And this is the DataGrid style:
<!-- DataGrid Styles ============ -->
<Style x:Key="StDataGrid2" TargetType="DataGrid" >
<Setter Property="RowHeaderWidth" Value="0" />
<Setter Property="RowHeight" Value="32" />
<Setter Property="RowBackground" Value="PowderBlue" />
<Setter Property="FontWeight" Value="Regular" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="ScrollViewer.CanContentScroll" Value="True" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="ColumnHeaderStyle" Value ="{DynamicResource stDghdr}" />
<Setter Property="Margin" Value="0,0,10,0" />
<Setter Property="Template">
<Setter.Value >
<ControlTemplate >
<Border BorderThickness="1" BorderBrush="#FF60727B">
<DockPanel Width="{Binding Path=ActualWidth, RelativeSource={RelativeSource
FindAncestor, AncestorType={x:Type Window}}}">
<StackPanel DockPanel.Dock="Top" Height="15" Orientation="Horizontal"
HorizontalAlignment="Left" CanHorizontallyScroll="False" Width="200" >
<RepeatButton x:Name="LineLeftButton" Width="90" Content="<"
Interval="1000" Delay="1000"
Command="{x:Static ScrollBar.LineLeftCommand}"
CommandTarget="{Binding ElementName=dgscrollviewer}"ClickMode="Hover" />
<RepeatButton x:Name="LineRightButton" Width="90" Content=">"
Interval="1000" Delay="1000"
Command="{x:Static ScrollBar.LineRightCommand}"
CommandTarget="{Binding ElementName=dgscrollviewer}" ClickMode="Hover"/>
</StackPanel>
<ScrollViewer x:Name="dgscrollviewer" CanContentScroll ="True"
VerticalScrollBarVisibility="Hidden" HorizontalScrollBarVisibility ="Auto">
<StackPanel Orientation="Vertical" Height="Auto"
HorizontalAlignment="Stretch" CanHorizontallyScroll="True">
<DataGridColumnHeadersPresenter HorizontalAlignment="Stretch"
Width="{Binding Path=ActualWidth, RelativeSource={RelativeSource
FindAncestor, AncestorType={x:Type Window}}}"
HorizontalContentAlignment="Stretch" Height= "32" Padding="0" Margin="0" />
<ItemsPresenter Height="300" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"/>
</StackPanel>
</ScrollViewer>
</DockPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="stDghdr" TargetType="DataGridColumnHeader" >
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value ="Stretch"/>
<Setter Property="Height" Value="25" />
<Setter Property="SeparatorBrush" Value="#79858b" />
<Setter Property="Padding" Value="5,0,5,0" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="FontSize" Value="12" />
<Setter Property="Background" Value ="LavenderBlush"/>
<Setter Property="BorderBrush" Value="#FF60727B"/>
<Setter Property="BorderThickness" Value="2,0,2,2"/>
</Style>
Here is a link to download the demo:
Demo
*Edit/ Update: I think the ColumnHeaders are scrolling faster because they are controlled by a different ScrollViewer? For instance, if I set a large FontSize property on the ScrollViewer that is in the DataGrid style, the text in the DataGrid cells gets bigger but not the text in the ColumnHeaders.
Any ideas or suggestions besides creating a ControlTemplate for the entire DataGrid? Thank you.

How to use different ItemsControl.ItemContainerStyle for different ItemsPanelTemplate

I have an ItemsControl which uses different ItemsPanelTemplate based on certain condition. I want to have different ItemContainerStyle for each ItemsPanelTemplate (in fact, I want ItemsContainerStyle for only one of the templates). How can I achieve that? Here is the code I am using:
<UserControl.Resources>
<ItemsPanelTemplate x:Key="UGridItemsPanelTemplate">
<UniformGrid Name="MyUGrid" Columns="{Binding Columns}" Rows="{Binding Rows}"/>
</ItemsPanelTemplate>
<ItemsPanelTemplate x:Key="GridItemsPanelTemplate">
<Grid Name="MyGrid" Loaded="MyGrid_Loaded"/>
</ItemsPanelTemplate>
</UserControl.Resources>
<Grid>
<!--ItemList has 1000+ items if IsMap is FALSE; using ItemsConatinerStyle in this case slows the UI down-->
<ItemsControl Name="MyPresenter" ItemsSource="{Binding ItemList}" Tag="{Binding IsMap}">
<ItemsControl.Style>
<Style TargetType="{x:Type ItemsControl}">
<Setter Property="ItemsPanel" Value="{StaticResource UGridItemsPanelTemplate}"/>
<Style.Triggers>
<Trigger Property="Tag" Value="TRUE">
<!--I want to use ItemContainerStyle only for this template-->
<Setter Property="ItemsPanel" Value="{StaticResource GridItemsPanelTemplate}"/>
</Trigger>
</Style.Triggers>
</Style>
</ItemsControl.Style>
<!--Use this style only if IsMap is TRUE-->
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContentControl}">
<ContentPresenter/>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Grid.Row" Value="{Binding GridRow}"/>
<Setter Property="Grid.Column" Value="{Binding GridColumn}"/>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border x:Name="Border1" Background="{Binding BorderVisible}"
BorderThickness="1" Padding="{Binding PaddingVal}">
<Button Name="ItemButton" Content="{Binding Label}" IsEnabled="{Binding IsButtonEnabled}" CommandParameter="{Binding}"/>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</UserControl>
Thanks,
RDV
I found a way, When IsMap is TRUE, set ItemsContainerStyle along with ItemsPanel. Updated code is posted below:
<UserControl.Resources>
<ItemsPanelTemplate x:Key="UGridItemsPanelTemplate">
<UniformGrid Name="MyUGrid" Columns="{Binding Columns}" Rows="{Binding Rows}"/>
</ItemsPanelTemplate>
<ItemsPanelTemplate x:Key="GridItemsPanelTemplate">
<Grid Name="MyGrid" Loaded="MyGrid_Loaded"/>
</ItemsPanelTemplate>
<Style x:Key="ClusterGridContainerStyle">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContentControl}">
<ContentPresenter/>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Grid.Row" Value="{Binding UnitGridRow}"/>
<Setter Property="Grid.Column" Value="{Binding UnitGridColumn}"/>
</Style>
</UserControl.Resources>
<Grid>
<!--ItemList has 1000+ items if IsMap is FALSE-->
<ItemsControl Name="MyPresenter" ItemsSource="{Binding ItemList}" Tag="{Binding IsMap}">
<ItemsControl.Style>
<Style TargetType="{x:Type ItemsControl}">
<Setter Property="ItemsPanel" Value="{StaticResource UGridItemsPanelTemplate}"/>
<Style.Triggers>
<Trigger Property="Tag" Value="TRUE">
<!--I want to use ItemContainerStyle only for this template-->
<Setter Property="ItemsPanel" Value="{StaticResource GridItemsPanelTemplate}"/>
<Setter Property="ItemContainerStyle" Value="{StaticResource ClusterGridContainerStyle}"/>
</Trigger>
</Style.Triggers>
</Style>
</ItemsControl.Style>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border x:Name="Border1" Background="{Binding BorderVisible}"
BorderThickness="1" Padding="{Binding PaddingVal}">
<Button Name="ItemButton" Content="{Binding Label}" IsEnabled="{Binding IsButtonEnabled}" CommandParameter="{Binding}"/>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</UserControl>

Draw ListViewItem outsite the canvas of the listview template

I have a ListView that its ItemsPanelTemplate is a Canvas, and every item is a rectangle.
I'm trying to draw a Rectangle outside the Canvas in the position of (-50,-50) with no successive. can I do that somehow ?
The XAML:
<Grid >
<ListView BorderThickness="0" BorderBrush="Transparent" ItemsSource="{Binding Rectangles}" Height="200" Width="200">
<ListView.Resources>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Canvas.Left" Value="{Binding Left, Mode=TwoWay}" />
<Setter Property="Canvas.Top" Value="{Binding Top, Mode=TwoWay}" />
</Style>
</ListView.Resources>
<ListView.ItemTemplate>
<DataTemplate DataType="{x:Type WpfApplication2:RectangleModel}">
<Rectangle Width="30" Height="30" Canvas.Left="{Binding Left}" Canvas.Right="{Binding Right}" Fill="LightCoral"
ClipToBounds="False"/>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="LightBlue"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
</Grid>
Code behind:
public partial class MainWindow : Window
{
public List<RectangleModel> Rectangles { get; set; }
public MainWindow()
{
Rectangles = new List<RectangleModel>();
Rectangles.Add(new RectangleModel { Left = -50, Top = -50 });
Rectangles.Add(new RectangleModel { Left = 0, Top = 0 });
Rectangles.Add(new RectangleModel { Left = 50, Top = 50 });
DataContext = this;
InitializeComponent();
}
}
I may be wrong, but this seems to be rather simple problem (I may have completely assumed the wrong thing, but I'm not sure so I'm going with the assumption just in case).
You've defined your ListView to be 200 by 200 and your Canvas is taking all that space. Judging by your picture, I feel it is Canvas that you want to be of 200 by 200 not the ListView.
Xaml:
<Grid >
<ListView BorderThickness="0" BorderBrush="Transparent" ItemsSource="{Binding Rectangles}">
<ListView.Resources>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Canvas.Left" Value="{Binding Left, Mode=TwoWay}" />
<Setter Property="Canvas.Top" Value="{Binding Top, Mode=TwoWay}" />
</Style>
</ListView.Resources>
<ListView.ItemTemplate>
<DataTemplate DataType="{x:Type wpfApplication1:RectangleModel}">
<Rectangle Width="30" Height="10" Canvas.Left="{Binding Left}" Canvas.Top="{Binding Top}" Fill="LightCoral"
ClipToBounds="False"/>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="LightBlue" ClipToBounds="False" Height="200" Width="200"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
</Grid>
Result:
Try this style (I removed the scrollviewer from the default tamplate):
I agree with the comments saying a control that draws like this is doubtful.
<Window x:Class="CanvasListView.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:CanvasListView="clr-namespace:CanvasListView"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
d:DataContext="{d:DesignInstance Type=CanvasListView:MainWindow,IsDesignTimeCreatable=True}"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<SolidColorBrush x:Key="ListBorder" Color="#828790"/>
<Style TargetType="{x:Type ListView}">
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
<Setter Property="BorderBrush" Value="{StaticResource ListBorder}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
<Setter Property="ScrollViewer.PanningMode" Value="Both"/>
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListView}">
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="1" SnapsToDevicePixels="true">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
</Trigger>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<ListView BorderThickness="0" BorderBrush="Transparent" ItemsSource="{Binding Rectangles}" Height="200" Width="200">
<ListView.Resources>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Canvas.Left" Value="{Binding Left, Mode=TwoWay}" />
<Setter Property="Canvas.Top" Value="{Binding Top, Mode=TwoWay}" />
</Style>
</ListView.Resources>
<ListView.ItemTemplate>
<DataTemplate DataType="{x:Type CanvasListView:RectangleModel}">
<Rectangle Width="30" Height="30" Fill="{Binding Color}"/>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="LightBlue"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
</Grid>
</Window>
I added a color property in the viewmodel:
public string Color { get; set; }
I did it via Popup, it looks well but I dont know whether it fits in your requirement or not
<Grid Background="Transparent">
<ListView BorderThickness="0" BorderBrush="Transparent" ItemsSource="{Binding Rectangles}" Height="200" Width="200">
<ListView.Resources>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Canvas.Left" Value="{Binding Left, Mode=TwoWay}" />
<Setter Property="Canvas.Top" Value="{Binding Top, Mode=TwoWay}" />
</Style>
</ListView.Resources>
<ListView.ItemTemplate>
<DataTemplate DataType="{x:Type WpfApplication2:RectangleModel}">
<Popup Width="30" Height="30" Canvas.Left="{Binding Left}" Canvas.Right="{Binding Right}"
IsOpen="True"
ClipToBounds="False">
<Rectangle Fill="LightCoral"/>
</Popup>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="LightBlue"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
</Grid>
This gives same result as you want. But you need to work more on that like their relative positions and all.

unable to drag Custom ScrollViewer in WrapPanel inside ItemsPanelTemplate

Unable to drag the scroll bar after implementing custom scrollviewer on listbox in a usercontrol.
its working fine for other usercontrols which has listbox.
Only difference between usercontrols is WrapPanel
<!--ListBoxItem Style-->
<Style x:Key="ListBoxItemStyle" TargetType="ListBoxItem">
<Setter
Property="FocusVisualStyle"
Value="{x:Null}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border
x:Name="ItemBorder"
BorderBrush="Transparent"
Background="Transparent"
BorderThickness="1" Margin="15"
>
<ContentPresenter/>
</Border>
<ControlTemplate.Triggers>
<Trigger
Property="IsSelected"
Value="True">
<Setter
TargetName="ItemBorder"
Property="Background"
Value="{StaticResource G2Brush}"/>
<Setter
TargetName="ItemBorder"
Property="BorderBrush"
Value="{StaticResource G4Brush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--ListBox Style-->
<Style TargetType="{x:Type ListBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBox}">
<ScrollViewer x:Name="ScrollViewer">
<ItemsPresenter/>
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<Border x:Name="border" Background="Transparent" Margin="2">
<Grid Width="70" Height="70">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="10"/>
</Grid.RowDefinitions>
<Border x:Name="borderImage" Background="Transparent" Grid.Row="0">
<Image Source="{Binding Path=FilePath}" />
</Border>
<TextBlock x:Name="ThumbFileName" Text="{Binding Path=FileName}" Grid.Row="1"
Style="{StaticResource ThumbFileName}" VerticalAlignment="Top" HorizontalAlignment="Left"
TextTrimming="CharacterEllipsis"
/>
</Grid>
</Border>
<DataTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="borderImage" Property="BorderBrush" Value="{StaticResource B1Brush}" />
<Setter TargetName="borderImage" Property="BorderThickness" Value="1" />
<Setter TargetName="ThumbFileName" Property="Foreground" Value="{StaticResource B1Brush}" />
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate >
<WrapPanel Margin="10"
Background="Red"
/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter
Property="ScrollViewer.HorizontalScrollBarVisibility"
Value="Disabled"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
</Style>
<Grid Background="Transparent">
<ListBox x:Name="reportListViewControl"
Background="Transparent"
Foreground="{StaticResource G4Brush}"
BorderThickness="0"
Style="{StaticResource ListBoxStyle}"
ItemContainerStyle="{StaticResource ListBoxItemStyle}"
Drop="reportListViewControl_Drop"
SelectionMode="Extended"
SelectionChanged="reportListViewControl_SelectionChanged"
AllowDrop="True">
</ListBox>
</Grid>
In your example WrapPanel takes all the space it needs to show its items. To enable scrollbars you can restrict it by the size of its parent, ListBox:
<ItemsPanelTemplate>
<WrapPanel Margin="10" Width="{Binding ActualWidth, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}}"
Height="{Binding ActualHeight, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}}"/>
</ItemsPanelTemplate>
Or you can use UniformGrid and control it with Columns or Rows property.

Resources