首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >绑定到ListBoxItem的ActualWidth

绑定到ListBoxItem的ActualWidth
EN

Stack Overflow用户
提问于 2012-10-12 11:45:11
回答 2查看 807关注 0票数 1

我有一个ListBox,它基本上是一个画布。项目应以Rectangles的形式显示。矩形的位置通过ListBoxItem's Canvas.LeftCanvas.Right属性绑定到项的数据。

这是ListBox' Template,它生成Canvas

代码语言:javascript
复制
<ListBox.Template>
    <ControlTemplate>
        <Canvas IsItemsHost="True"/>
    </ControlTemplate>
</ListBox.Template>

ListBox' ItemContainerStyle设置项目的位置:

代码语言:javascript
复制
<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看起来是这样的:

代码语言:javascript
复制
<DataTemplate>
    <Rectangle Height="..." 
       Width="{Binding ActualWidth,
         RelativeSource={RelativeSource FindAncestor, AncestorType=ListBoxItem}}" 
       Fill="..."/>
</DataTemplate>

但是,应用此绑定后,将不会显示矩形。当我设置一个恒定宽度时,一切都会正确地呈现出来。

有办法在Canvas中设置矩形的位置吗?

更新

使用WPF树可视化器,我意识到这可能是ContentPresenter's ActualWidth的一个问题。以下屏幕快照显示正确设置了Canvas.LeftCanvas.Right属性:

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

此外,我还要修改我的上述声明。用一个ContentPresenter包围Border不会产生正确的结果。相反,整个布局似乎是腐败的。

更新2

MSDN说明如下:

子元素的Canvas.Right偏移量不影响父画布的大小。 如果指定这些属性,则附加属性Canvas.Top或Canvas.Left优先于Canvas.Bottom或Canvas.Right属性。

因此,我似乎必须显式地指定宽度,这对于适当的转换器来说应该是一个小问题。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-10-12 16:07:39

正如问题中所述,仅用Canvas.LeftCanvas.Right属性定义控件的大小是不可能的。

想要的行为可以通过如下的转换器来实现(省略错误处理):

代码语言:javascript
复制
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();
    }
}

使用(添加转换器作为资源):

代码语言:javascript
复制
<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>
票数 0
EN

Stack Overflow用户

发布于 2012-10-12 12:48:36

首先,您可以更容易地做到以下几点:

代码语言:javascript
复制
<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不适合其主机控件。您可能只想使用带有BorderBackground和/或BorderThickness&BorderBrush

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12858360

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档