我有一个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树可视化器,我意识到这可能是ContentPresenter's ActualWidth的一个问题。以下屏幕快照显示正确设置了Canvas.Left和Canvas.Right属性:

但是,ActualWidth属性设置为4(包含Rectangle的StrokeThickness为4)。如何解决这个布局问题?
此外,我还要修改我的上述声明。用一个ContentPresenter包围Border不会产生正确的结果。相反,整个布局似乎是腐败的。
更新2
MSDN说明如下:
子元素的Canvas.Right偏移量不影响父画布的大小。 如果指定这些属性,则附加属性Canvas.Top或Canvas.Left优先于Canvas.Bottom或Canvas.Right属性。
因此,我似乎必须显式地指定宽度,这对于适当的转换器来说应该是一个小问题。
发布于 2012-10-12 16:07:39
正如问题中所述,仅用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>发布于 2012-10-12 12:48:36
首先,您可以更容易地做到以下几点:
<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&BorderBrush。
https://stackoverflow.com/questions/12858360
复制相似问题