1

我有一个ListBox,它基本上是一个画布。项目应显示为Rectangles。矩形的位置通过ListBoxItem's Canvas.LeftandCanvas.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.LeftandCanvas.Right属性设置正确: 树可视化器的屏幕截图

但是,该ActualWidth属性设置为 4(StrokeThickness包含的Rectangle是 4)。如何解决这个布局问题?

此外,我必须修改我的上述陈述。ContentPresenter用 a包围Border不会产生正确的结果。相反,整个布局似乎已损坏。

更新 2

MSDN 说如下:

子元素的 Canvas.Right 偏移量不会影响父 Canvas 的大小。

如果您指定它们,附加属性 Canvas.Top 或 Canvas.Left 优先于 Canvas.Bottom 或 Canvas.Right 属性

所以看来我必须明确指定宽度,这应该是适当转换器的一个小问题。

4

2 回答 2

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不对其主机控制大小。您可能只想将 aBorder与 aBackground和/或BorderThickness&一起使用BorderBrush

于 2012-10-12T12:48:36.773 回答
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>
于 2012-10-12T16:07:39.370 回答