I have a ListBox
, which is basically a canvas. The items shall be displayed as Rectangles
. The position of the rectangles are bound to the items' data via the ListBoxItem's
Canvas.Left
and Canvas.Right
property.
This is the ListBox'
Template
, which generates the Canvas
:
<ListBox.Template>
<ControlTemplate>
<Canvas IsItemsHost="True"/>
</ControlTemplate>
</ListBox.Template>
The ListBox'
ItemContainerStyle
sets the position of the items:
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<ContentPresenter/>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Canvas.Left">
<Setter.Value>
<MultiBinding Converter="{StaticResource ...}">
...
</MultiBinding>
</Setter.Value>
</Setter>
<Setter Property="Canvas.Right">
<Setter.Value>
<MultiBinding Converter="{StaticResource ...}">
...
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
This actually works. When I surround the ContentPresenter
with a border, the border has the correct position and size.
Now, the rectangle's Width
should equal the ListBoxItem's
actual width. So the ItemTemplate
looks like this:
<DataTemplate>
<Rectangle Height="..."
Width="{Binding ActualWidth,
RelativeSource={RelativeSource FindAncestor, AncestorType=ListBoxItem}}"
Fill="..."/>
</DataTemplate>
But with this binding applied, the rectangle is never displayed. When I set a constant width, everything renders correctly.
Is there a way to set the rectangle's position within the Canvas
?
Update
Using the WPF Tree Visualizer I realized that this is probably a problem of the ContentPresenter's
ActualWidth
. The following screenshot shows that the Canvas.Left
and Canvas.Right
property are set correctly:
However, the ActualWidth
property is set to 4 (the StrokeThickness
of the contained Rectangle
is 4). How can this layout problem be solved?
Furthermore, I have to amend my statement of above. Surrounding the ContentPresenter
with a Border
does not produce a correct result. Instead, the entire layout seems corrupt.
Update 2
The MSDN says the following:
The Canvas.Right offset of a child element does not affect the size of a parent Canvas.
If you specify them, the attached properties Canvas.Top or Canvas.Left take priority over Canvas.Bottom or Canvas.Right properties
So it seems that I have to specify the width explicitly, which should be a minor problem with an appropriate converter.
As stated in the question, it is not possible to define a control's size only with the
Canvas.Left
andCanvas.Right
properties.The wanted behaviour could be achieved with a converter like the following (error handling omitted):
Use (add the converter as a resource):