我有ListBox
,基本上是画布。这些项目应显示为Rectangles
。矩形的位置通过ListBoxItem's
Canvas.Left
和Canvas.Right
属性绑定到项目的数据。
这是ListBox'
Template
,生成Canvas
:
<ListBox.Template>
<ControlTemplate>
<Canvas IsItemsHost="True"/>
</ControlTemplate>
</ListBox.Template>
ListBox'
ItemContainerStyle
设置项目的位置:
<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>
这实际上有效。当我用边框包围ContentPresenter
时,边框的位置和大小正确。
现在,矩形的Width
应该等于ListBoxItem's
实际宽度。所以ItemTemplate
看起来像这样:
<DataTemplate>
<Rectangle Height="..."
Width="{Binding ActualWidth,
RelativeSource={RelativeSource FindAncestor, AncestorType=ListBoxItem}}"
Fill="..."/>
</DataTemplate>
但是应用此绑定后,永远不会显示矩形。当我设置一个恒定的宽度时,一切都正确呈现。
有没有办法在Canvas
?
使用WPF Tree Visualizer我意识到这可能是ContentPresenter's
ActualWidth
的一个问题。以下屏幕截图显示Canvas.Left
和Canvas.Right
属性设置正确:
但是,ActualWidth
属性设置为4(包含StrokeThickness
的{{1}}为4)。如何解决这个布局问题?
此外,我必须修改上述声明。使用Rectangle
围绕ContentPresenter
不会产生正确的结果。相反,整个布局似乎都是腐败的。
MSDN说明如下:
子元素的Canvas.Right偏移量不会影响父Canvas的大小。
如果指定它们,附加属性Canvas.Top或Canvas.Left优先于Canvas.Bottom或Canvas.Right属性
所以我似乎必须明确指定宽度,这应该是适当转换器的一个小问题。
答案 0 :(得分:1)
首先,您可以更轻松地执行以下操作:
<ListBox>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Canvas.Left" Value="..."/>
<Setter Property="Canvas.Top" Value="..."/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
其次,Rectangle
不会调整其主机控件的大小。您可能只想使用Border
代替Background
和/或BorderThickness
&amp; BorderBrush
。
答案 1 :(得分:0)
如问题中所述,仅使用Canvas.Left
和Canvas.Right
属性无法定义控件的大小。
可以通过以下转换器实现所需行为(省略错误处理):
public class CanvasWidthConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var canvasLeft = (double)values[0];
var canvasRight = (double)values[1];
return canvasRight - canvasLeft;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
使用(将转换器添加为资源):
<Style TargetType="ListBoxItem">
<Setter Property="Canvas.Left" Value="{Binding LeftValue}"/>
<Setter Property="Width">
<Setter.Value>
<MultiBinding Converter="{StaticResource CanvasWidthConverter}">
<Binding Path="LeftValue"/>
<Binding Path="RightValue"/>
</MultiBinding>
</Setter.Value>
</Setter>
</Style>