如何在Silverlight 3中将Canvas用作ItemsConnel的ItemsPanel

时间:2010-03-05 00:56:30

标签: silverlight silverlight-3.0 listbox canvas

我正在尝试使用Silverlight 3在ItemsControl DataTemplate中设置Canvas属性。根据this post,唯一的方法是使用ItemsContainerStyle为ContentPresenter类型设置它,因为仅限Canvas属性对画布的直接儿童生效。这似乎在SL3中不起作用,因为ItemsControl没有ItemsContainerStyle属性,所以我尝试了this article建议的ListBox,但它仍然不起作用。从下面的XAML,我希望看到一个绿色方块,数字10,30,50,70从“NW”到“SE”方向连着。任何人都可以告诉我为什么他们都在NW角落里堆叠在一起吗?

<UserControl x:Class="TestControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:System="clr-namespace:System;assembly=mscorlib" >
    <StackPanel>
        <ListBox>
            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <Canvas Background="Green" Width="100" Height="100" />
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBox Text="{Binding}" />
                </DataTemplate>                
            </ListBox.ItemTemplate>
            <ListBox.ItemContainerStyle>
                <Style TargetType="ContentPresenter">
                    <Setter Property="Canvas.Left" Value="{Binding}" />
                    <Setter Property="Canvas.Top" Value="{Binding}" />
                </Style>
            </ListBox.ItemContainerStyle>
            <ListBox.Items>
                <System:Int32>10</System:Int32>
                <System:Int32>30</System:Int32>
                <System:Int32>50</System:Int32>
                <System:Int32>70</System:Int32>
            </ListBox.Items>
        </ListBox>
    </StackPanel>
</UserControl>

4 个答案:

答案 0 :(得分:7)

我不确定它是否适用于您的场景,但我过去使用RenderTransform完成了这项工作。

<ItemsControl>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas Background="Green" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBox Text="{Binding}">
                <TextBox.RenderTransform>
                    <TranslateTransform X="100" Y="100" />
                </TextBox.RenderTransform>
            </TextBox>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    <ItemsControl.Items>
        <System:Int32>10</System:Int32>
        <System:Int32>30</System:Int32>
        <System:Int32>50</System:Int32>
        <System:Int32>70</System:Int32>
    </ItemsControl.Items>
</ItemsControl>

或者在绑定的情况下,您需要使用转换器

<ItemsControl>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas Background="Green" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBox Text="{Binding}" RenderTransform="{Binding Converter={StaticResource NumberToTransformGroupConverter}}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    <ItemsControl.Items>
        <System:Int32>10</System:Int32>
        <System:Int32>30</System:Int32>
        <System:Int32>50</System:Int32>
        <System:Int32>70</System:Int32>
    </ItemsControl.Items>
</ItemsControl>

转换器

public void ConvertTo(object value, ...)
{
    int intValue = int.Parse(value.ToString());

    return new TransformGroup()
    {
        Children = new TransformCollection()
        {
            new TranslateTransform { X = intValue, Y = intValue }
        }
    };
}

答案 1 :(得分:3)

Silverlight4不会绑定到样式中的附加属性。我建议使用David Anson描述的here方法。

    <UserControl.Resources>
    <Style  x:Key="ScreenBindStyle" TargetType="ListBoxItem">
        <Setter Property="Helpers:SetterValueBindingHelper.PropertyBinding">
            <Setter.Value>
                <Helpers:SetterValueBindingHelper>
                    <Helpers:SetterValueBindingHelper Type="Canvas" Property="Left" Binding="{Binding LocationField.Value.X}" />
                    <Helpers:SetterValueBindingHelper Type="Canvas" Property="Top" Binding="{Binding LocationField.Value.Y}" />
                    <Helpers:SetterValueBindingHelper Type="Canvas" Property="ZIndex" Binding="{Binding ZIndex.Value}" />
                </Helpers:SetterValueBindingHelper>
            </Setter.Value>
        </Setter>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ListBoxItem">
                    <ContentPresenter/>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</UserControl.Resources>

在列表框中:

ItemContainerStyle="{StaticResource ScreenBindStyle}"

答案 2 :(得分:2)

旧帖但我遇到了同样的问题,但现在使用SL5,现在允许样式设置器中的Binding。我试图避免使用ListBox(因为它处理选择等),而ItemsControl仍然没有ItemContainerStyle。所以我尝试了一些事情。

我没有找到很多讨论这个问题的主题,所以让我分享我的解决方案(对不起,如果它重复)

事实上,通过在Style资源中添加未命名的ItemsControl,我找到了一种非常方便的方法来解决问题:

<ItemsControl ItemsSource="{Binding Path=MyData}">
    <ItemsControl.Resources>
        <Style TargetType="ContentPresenter">
            <Setter Property="Canvas.Top" Value="{Binding Path=Bounds.Top}"/>
            <Setter Property="Canvas.Left" Value="{Binding Path=Bounds.Left}"/>
            <Setter Property="Width" Value="{Binding Path=Bounds.Width}"/>
            <Setter Property="Height" Value="{Binding Path=Bounds.Height}"/>
        </Style>
    </ItemsControl.Resources>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate DataType="my:DataType">
            ...
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

像SL5中的魅力一样:)

答案 3 :(得分:0)

我无法解释你所看到的。你的Xaml至少在几个方面被打破了。

首先,Xaml本身失败,因为: -

<Style TargetType="ContentPresenter">

应该是

<Style TargetType="ContentControl">

ListBox案例中的项容器类型为ListBoxItem,派生自ContentControl

仍然没有这样,在样式设置器中放置{Binding}仍然不起作用。我想你想象的是,样式将依次应用于每个项目并从当前项目中获取其值。但是,即使绑定在样式中工作,也只有一个样式,它将从ListBox DataContext获取其数据绑定。这是一个不同的DataContext,适用于每个ListBox项(在本例中是Items集合中的每个Item)。

我仍然认为Ben有一个合理的解决方案可以消除这种方法。