Silverlight 3 - 数据绑定画布上矩形的位置

5

我目前正在尝试使用ItemsControl将一组对象绑定到Silverlight 3中的Canvas,如下所示:

<ItemsControl x:Name="ctrl" ItemsSource="{Binding myObjectsCollection}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas></Canvas>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Rectangle Stroke="LightGray" Fill="Black"  StrokeThickness="2" 
                   RadiusX="15" RadiusY="15" Canvas.Left="{Binding XAxis}"
                   Height="25" Width="25">
            </Rectangle>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

很不幸,似乎Canvas.Left的绑定被忽略了。从我所学到的这里来看,这似乎是由于项目被放置在内容呈现器中而不是我在项目面板中指定的实际画布。

是否有一种方法可以使用数据绑定来确定画布上元素的位置?

5个回答

7

我知道这个问题已经有了一个被接受的答案,但是实现最初的目标而不混乱地处理边距的方法是创建一个自定义的ItemsControl并覆盖PrepareContainerForItemOverride方法。在这个方法中,您可以通过代码设置绑定。

public class CustomItemsCollection
    : ItemsControl
{
    protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
    {

        FrameworkElement contentitem = element as FrameworkElement;
        Binding leftBinding = new Binding("Left"); // "Left" is the property path that you want to bind the value to.
        contentitem.SetBinding(Canvas.LeftProperty, leftBinding);

        base.PrepareContainerForItemOverride(element, item);
    }

}

2

在Silverlight中,您无法使用ItemsControl.ItemContainerStyle。它不存在。它只存在于一些叶级类(如ListBox)本身。


1

我知道这个问题有点老,但你可以使用一个渲染变换——我正在做类似的事情。

<ItemsControl ItemsSource="{Binding Notes}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas Background="Aqua"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Border Width="{Binding W}" Height="{Binding H}" BorderBrush="Navy" BorderThickness="5" CornerRadius="10">
                <TextBlock Text="{Binding Text}"/>
                <Border.RenderTransform>
                    <TransformGroup>
                        <RotateTransform Angle="0"/>
                        <TranslateTransform X="{Binding X}" Y="{Binding Y}"/>
                    </TransformGroup>
                </Border.RenderTransform>
            </Border>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

1

你说得对,在 Canvas 和 Rectangle 之间插入了 ContentPresenter。 一个解决方法是设置左边距而不是 Canvas.Left

<Rectangle Stroke="LightGray" Fill="Black" StrokeThickness="2" 
      RadiusX="15" RadiusY="15" Height="25" Width="25">
    <Rectangle.Margin>
        <Thickness Left="{Binding XAxis}"/>
    </Rectangle.Margin>
</Rectangle>

很遗憾,Left属性是只读的,无法设置。 - Blounty
1
我不知道为什么它是只读的。 不管怎样,我使用值转换器成功地解决了这个问题: <Rectangle ... Margin="{Binding XAxis, Converter={StaticResource LeftMarginConverter}}"/> 但这绝对不是一个优雅的解决方案。 - Mart
LeftMarginConverter是如何工作的?当应用它时,边距是否相对于容器的左边缘应用于所有绑定项? - Blounty
1
转换器是: public class LeftMarginConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return new Thickness((int)value, 0, 0, 0); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } 这样就设置了左偏移量。如果您使用Margin={Binding}进行绑定,可以根据对象的属性想象任何其他定位。 - Mart

-2
将以下内容添加到您的ItemsControl中。
 <ItemsControl.ItemContainerStyle>
    <Style TargetType="{x:Type ContentPresenter}">
      <Setter Property="Canvas.Left" Value="{Binding XPath=XAxis}"/>
    </Style>
  </ItemsControl.ItemContainerStyle>

不需要任何自定义控件


1
这是不可行的,因为在Silverlight(v3或v4)中ItemsControl没有ItemContainerStyle属性。在WPF中有,但这不是问题的关键。 - Anthony

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接