WPF menu styled listbox (MVVM) - wpf

I want to create a menu which tracks the selected item, so I'm using nested ListBoxes (since the options for Selectors are quite limited. The main ListBox is arranged horizontally, and each ListBoxItem contains a TextBlock and a StackPanel with another ListBox (this one displays vertically) to show "MenuItems" (which I also need to track the selected item). Like this:
<ListBox DockPanel.Dock="Top" Grid.Column="0" ItemsSource="{Binding DashBoards}"
IsSynchronizedWithCurrentItem="True" SelectedItem="{Binding SelectedDashBoard}">
<ListBox.Template>
<ControlTemplate TargetType="{x:Type ListBox}">
<DockPanel>
<ScrollViewer x:Name="scrollviewer" HorizontalScrollBarVisibility="Hidden" CanContentScroll="False">
<StackPanel IsItemsHost="True" Orientation="Horizontal" />
</ScrollViewer>
</DockPanel>
</ControlTemplate>
</ListBox.Template>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Name}" />
<dx:DXExpander IsExpanded="{Binding IsSelected}">
<ListBox ItemsSource="{Binding Sections}"
IsSynchronizedWithCurrentItem="True" SelectedItem="{Binding SelectedSection}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Metadata.Name}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</dx:DXExpander>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I managed to display this ListBox on top of other controls, so it looks like a menu.
Now with the problem... when I select an item in the horizontal ListBox, the Expander expands ok, but the ListBox grows in height so all other items look like they expanded too.
How can I get to expand ONLY the selected item, without changing the height of the ListBox?
In other words, how can I get one of the vertical ListBoxes to overflow its parent container (aka the horizontal ListBox)?
I think I need to re-structure everything, but I have no clue how to begin. I've found some solutions that use a Canvas, but they don't seem to work in this case.
Any help is welcome and will be diligently upvoted ;-)
(Note: just in case it was not clear before, I need to know which element is selected in the horizontal ListBox, and also which one is selected in each individual vertical ListBox. This binds to the corresponding ViewModel which tracks selection, and both the horizontal and vertical ListBoxes are populated dynamically, so no way to define them in XAML)

You could move the selected style out of the data template so it's not applied to all items.
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="ListViewItem">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Height" Value="90"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<ListView>
<ListView.Items>
<sys:String>a</sys:String>
<sys:String>b</sys:String>
<sys:String>c</sys:String>
<sys:String>d</sys:String>
<sys:String>e</sys:String>
</ListView.Items>
</ListView>
</Grid>
</Window>
EDIT: after properly reading what you were after, I don't have your expander class or the item that you're binding to so I'm using Expander and MenuItem but this gives an example of using a listview as a menu with selectable items, maybe it'll help solve your problem, I'm assuming your expander control hides the actual expander button.
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ListView Height="16" VerticalAlignment="Top">
<ListView.Resources>
<Style TargetType="ListViewItem">
<Setter Property="Margin" Value="0,0,10,0"/>
</Style>
</ListView.Resources>
<ListView.Template>
<ControlTemplate TargetType="{x:Type ListBox}">
<StackPanel Background="LightGray" IsItemsHost="True" Orientation="Horizontal" />
</ControlTemplate>
</ListView.Template>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" ClipToBounds="False">
<TextBlock Text="{Binding Header}" />
<Canvas>
<Expander IsExpanded="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ListViewItem}}">
<Expander.Style>
<Style TargetType="{x:Type Expander}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Expander}">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="3" SnapsToDevicePixels="true">
<DockPanel>
<ContentPresenter x:Name="ExpandSite" DockPanel.Dock="Bottom" Focusable="false" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" Visibility="Collapsed" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</DockPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded" Value="true">
<Setter Property="Visibility" TargetName="ExpandSite" Value="Visible"/>
</Trigger>
<Trigger Property="ExpandDirection" Value="Right">
<Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Right"/>
</Trigger>
<Trigger Property="ExpandDirection" Value="Up">
<Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Top"/>
</Trigger>
<Trigger Property="ExpandDirection" Value="Left">
<Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Left"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Expander.Style>
<ListView ItemsSource="{Binding Items}" IsSynchronizedWithCurrentItem="True" />
</Expander>
</Canvas>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListView.Items>
<MenuItem Header="File">
<MenuItem.Items>
<MenuItem Header="Open" IsHitTestVisible="False"/>
<MenuItem Header="Exit" IsHitTestVisible="False"/>
</MenuItem.Items>
</MenuItem>
<MenuItem Header="Edit">
<MenuItem.Items>
<MenuItem Header="Cut" IsHitTestVisible="False"/>
<MenuItem Header="Copy" IsHitTestVisible="False"/>
<MenuItem Header="Paste" IsHitTestVisible="False"/>
</MenuItem.Items>
</MenuItem>
</ListView.Items>
</ListView>
</Grid>
</Window>

Related

Modify a child control from trigger or better way to change their foreground?

I have a listbox with a template, inside the listboxitem I have 2 textblock.
My goal is to change the foreground of those 2 textblock when the listboxitem is:
Hovered(Mouse over)
Selected
My ItemTemplate currently removes the highlight when u hover over items, that works as expected.
I know I can get the IsSelected and IsMouseOver events, for example:
<Trigger Property="IsSelected" Value="true">
<Setter Property="Background" TargetName="Bd" Value="White"/>
<!-- I have no idea how to access the textblock child of the listboxitem to change it -->
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<!-- I have no idea how to access the textblock child of the listboxitem to change it -->
</Trigger>
But I could not figure out how to modify the TextBlock inside, I've tried using acestor and a whole different ways none worked(as in they had no effect).
Here is what my View looks like:
<UserControl x:Class="Shex.Views.SideBarView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Shex.Views"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:shex="clr-namespace:Shex"
mc:Ignorable="d"
d:DesignHeight="800" d:DesignWidth="260"
Background="#403f42" Padding="0" BorderThickness="0" Margin="0">
<UserControl.Resources>
<Style x:Key="MenuContainerStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="0" Background="{TemplateBinding Background}"
Padding="0" SnapsToDevicePixels="true">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Background" TargetName="Bd" Value="White"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid Margin="0">
<ListBox ItemsSource="{Binding MenuItems}" SelectionMode="Single" SelectedItem="{Binding SelectedMenuItem}" SelectionChanged="{s:Action ChangeView}"
BorderThickness="0" Padding="0" Margin="0 10 0 0" Background="#403f42" ItemContainerStyle="{DynamicResource MenuContainerStyle}" SnapsToDevicePixels="true">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Height="60" Orientation="Horizontal" SnapsToDevicePixels="true">
<TextBlock Text="{Binding Image}" FontFamily="/Shex;component/Fonts/Font Awesome 5 Free-Solid-900.otf#Font Awesome 5 Free Solid" Foreground="#cfced1" FontSize="20" Margin="10 6 0 0" Width="30" VerticalAlignment="Center" HorizontalAlignment="Left"/>
<TextBlock Text="{Binding Name}" Foreground="#cfced1" FontSize="20" Margin="10 6 0 0" VerticalAlignment="Center" HorizontalAlignment="Left"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</UserControl>
You should add the trigger(s) to the ItemTemplate, e.g.:
<DataTemplate>
<StackPanel ...>
<TextBlock x:Name="tb1" ... />
<TextBlock x:Name="tb2" ... />
</StackPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType=ListBoxItem}}" Value="True">
<Setter TargetName="tb1" Property="Foreground" Value="Blue" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
A ListBoxItem style cannot set properties of some individual TextBlock or any other control that is defined in the ItemTemplate.

How to keep highlighting selected item of listbox even listbox lost focus?

I have a ListBox with ItemsSource binding to an ObservableCollection<Item>.
Item has two string properties Name and Description.
DataTemplate for Item is StackPanel with Children: TextBlock with Text Bind to Name, TextBox with Text bind to Description.
What I have now:
1. When cursor is in TextBox corresponding to Description of an item, the corresponding ListBoxItem is highlighted.
2. I can use Tab to navigate among item's Textbox
3. If I move cursor to another named TextBox(theTextBox in code below) outside of listbox, the selected item do not highlight any more. That is my problem.
The png at https://drive.google.com/file/d/1tyxaBLnnjFUCJRTsHbwBwSvdU_X_L1fn/view?usp=sharing help explains my problem.
<DockPanel>
<ListBox ItemsSource="{Binding Items}" DockPanel.Dock="Top" Height="100" KeyboardNavigation.TabNavigation="Cycle">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Focusable" Value="False"/>
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="Background" Value="LightGreen" />
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<ItemContainerTemplate >
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Name}"/>
<TextBox Text="{Binding Description}"/>
</StackPanel>
</ItemContainerTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBox Name-"theTextBox" AcceptsReturn="True" />
</DockPanel>
The background when not focussed is different because it uses a different brush.
If this is something you want to apply to everything and you don't care whether they're focussed or not then you could over-ride the system colour.
In a resource dictionary merged by app.xaml add:
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}"
Color={x:Static SystemColors.HighlightColor}"/>
This is the style that I use globally for ListBoxItems that includes keeping the selected item highlighted even when the control loses focus.
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<!-- Revert to the "Windows 7" style template that used "SystemColors.HighlightBrushKey" etc -->
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border
x:Name="ItemBorder"
Padding="{TemplateBinding Padding}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
<ControlTemplate.Triggers>
<!-- Use the same colours for selected items, whether or not the control has focus -->
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="ItemBorder" Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}" />
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Trigger command when ListBox selected item changes

I am trying to set up a sort of menu using ListBox and buttons as ListBoxItems to trigger a command when selection changes, but the result is that some times the selected ListBoxItem is changed but the command is not triggered, other times the opposite. The XAML is the following:
<Window.Resources>
<DataTemplate DataType="{x:Type viewModels:TripViewModel}">
<views:TripView />
</DataTemplate>
<DataTemplate DataType="{x:Type viewModels:AddTripViewModel}">
<views:AddTripView />
</DataTemplate>
<Style TargetType="{x:Type Button}">
<Setter Property="Height"
Value="50" />
<Setter Property="Background"
Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border>
<Grid Background="Transparent">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Padding"
Value="3" />
<Setter Property="Background"
Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border BorderBrush="Transparent"
BorderThickness="0"
Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="Background"
Value="DarkCyan" />
</Trigger>
<Trigger Property="IsSelected"
Value="True">
<Setter Property="Background"
Value="DarkCyan" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Window.Content>
<DockPanel Margin="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Height="Auto"
Width="Auto"
LastChildFill="True">
<!-- Left Panel -->
<Border BorderBrush="Black"
BorderThickness="0,0,1,0">
<StackPanel DockPanel.Dock="Left"
Margin="0"
Background="#555D6F">
<!-- First Row: Stacco Image -->
<Image Height="183"
Width="275"
Margin="3"
Source="/Media/stacco.png" />
<!-- Second Row: Buttons -->
<ScrollViewer CanContentScroll="True"
VerticalAlignment="Stretch"
VerticalScrollBarVisibility="Auto"
Margin="0,10,0,0">
<ListBox Name="MenuButtons"
ItemsSource="{Binding PageViewModels}"
Background="#555D6F"
IsSynchronizedWithCurrentItem="True">
<ListBox.ItemTemplate>
<ItemContainerTemplate>
<Button Content="{Binding Name}"
Command="{Binding DataContext.ChangePageCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
Margin="0" />
</ItemContainerTemplate>
</ListBox.ItemTemplate>
</ListBox>
</ScrollViewer>
</StackPanel>
</Border>
<!-- Control Area: Different View made by controls -->
<ContentControl DockPanel.Dock="Right"
Content="{Binding CurrentPageViewModel}" />
</DockPanel>
</Window.Content>
Am I doing right trying to insert a button in the ItemContainerTemplate? Would it be better to use the code behind to trigger the selection changed?

WPF apply triggers to listview items to change background

I am trying to create a sort of left menu for navigation inside the desktopapplication. My idea is to use Buttons as Listview items which should behave in this way: when i hover with the mouseover them theri background should change color (becomes darkCyan) and when i click one its background color should change persistently (to darkCyan) until i click on another button of the list. The problem is that i am using a the DataTemplate property to specify how the buttons should look like and I am tryin to apply the triggers to change the background color on the ControlTemplate of the ListView. The result is that sometimes the background color changes but the command related to the button is not fired other times the contrary. I think that I am doing the things in the wrong element of the tree view, but I don't have enough knowledge of the tree view so I am not understanding what I am doing wrong. Here is the code of the XAML in which i define the styles for the Buttons and the ListView
<Window.Resources>
<DataTemplate DataType="{x:Type viewModels:TripViewModel}">
<views:TripView />
</DataTemplate>
<Style TargetType="{x:Type Button}">
<Setter Property="Height"
Value="50" />
<Setter Property="Background"
Value="#555D6F" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border>
<Grid Background="Transparent">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border BorderBrush="Transparent"
BorderThickness="0"
Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="Background"
Value="DarkCyan" />
</Trigger>
<Trigger Property="IsSelected"
Value="True">
<Setter Property="Background"
Value="DarkCyan" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
And here is the code in which I create the ListView
<ListView Name="MenuButtons"
ItemsSource="{Binding PageViewModels}"
Background="Transparent"
IsSynchronizedWithCurrentItem="True">
<ListView.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Name}"
Command="{Binding DataContext.ChangePageCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
Margin="0" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Anyone can help?
Thanks
I have solved the issue by using a ListBox instead of a ListView and setting the ItemContainer to be a button in the following way
<ListBox.ItemTemplate>
<ItemContainerTemplate>
<Button Content="{Binding Name}"
Command="{Binding DataContext.ChangePageCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
Margin="0" />
</ItemContainerTemplate>
</ListBox.ItemTemplate>

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.

Resources