24

我正在尝试将集合绑定到 ItemsControl,将 Canvas 作为项目面板,并将每个项目的 Canvas.Left 和 Top 绑定到项目对象的属性。基本上,我正在尝试重新创建我在博客上的这篇文章中描述的二维数据绑定,但这次是在 WinRT 而不是 WPF 中。

由于 ItemsControl 将您的 ItemTemplate 内容包装在另一个 UI 元素(在 WinRT 的情况下为 ContentPresenter)中,并且这些包装器/容器元素直接放置在项目面板内,因此必须在这些容器上设置 Left 和 Top;您不能只在 DataTemplate 中设置它们。在 WPF 中,使用 ItemContainerStyle 中的绑定很容易做到这一点,例如:

<ItemsControl.ItemContainerStyle>
    <Style>
        <Setter Property="Canvas.Left" Value="{Binding Path=X}"/>
        <Setter Property="Canvas.Top" Value="{Binding Path=Y}"/>
    </Style>
</ItemsControl.ItemContainerStyle>

但是当我在 WinRT/XAML 项目中尝试同样的事情时,我什么也得不到。甚至没有绑定错误。如果我硬编码一个值,它会起作用;但如果我使用绑定,该属性将保持其默认值(零),并且“输出”窗口中不会显示任何绑定错误。

<ItemsControl.ItemContainerStyle>
    <Style TargetType="ContentPresenter">
        <!-- This works, so ItemContainerStyle does work in WinRT: -->
        <Setter Property="Canvas.Left" Value="200"/>
        <!-- But this silently fails, leaves Top as 0, and does not show
             any binding errors in the debugger's Output window: -->
        <Setter Property="Canvas.Top" Value="{Binding Y}"/>
    </Style>
</ItemsControl.ItemContainerStyle>

我已经验证 ContentPresenters 确实具有正确的 DataContext(即集合项,而不是集合本身或其他时髦的东西),因此您会认为这些绑定可以正常工作。但他们似乎甚至没有得到评估。如果我在其他任何地方放置了错误的绑定并运行调试构建,我会在调试器的输出窗口中看到绑定错误;但是如果我在我的 ItemContainerStyle 中引用了一个无意义的属性,则不会显示绑定错误。

这是一个更完整的示例,(据我所知)在 WPF 中应该可以正常工作,但是在 WinRT 中将所有内容留在原点:

<ItemsControl ItemsSource="{Binding Tiles}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemContainerStyle>
        <Style TargetType="ContentPresenter">
            <Setter Property="Canvas.Left" Value="{Binding DataContext.Left}"/>
        </Style>
    </ItemsControl.ItemContainerStyle>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Rectangle Width="80" Height="80" Fill="Gray"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

我已经尝试了一些更奇特的选项Binding——特别是RelativeSource。当我使用RelativeSource TemplatedParent时,无所事事的行为没有改变。但是,当我使用时RelativeSource Self,我确实收到了一个绑定错误,说该属性在 type 上不存在Setter!这Self有点太字面意思了,那里。

我也玩过 . TemplateBinding,但我从来没有真正理解过它应该用来做什么,我得到的只是一些难以理解的 COM 错误(欢迎使用 WinRT,这是一个巨大的技术倒退)。

我怎样才能(a)使绑定正常工作(是否有其他选项Binding可以用来强制它正常工作?),或者(b)以其他方式允许我中的项目基于数据绑定ItemsContainer任意定位到Canvas集合项目的属性?

4

3 回答 3

14

Setter 不支持绑定。我认为 Silverlight 仅在版本 5 中获得了它们。对于解决方法,您可以在此处查看我的旧文章。基本上,您定义一个附加的依赖属性,为您设置绑定。

于 2012-08-08T16:33:58.513 回答
8

在 silverlight 和 winrt/metro/8.1 中应用 RenderTransform 似乎对我很有效:

<ItemsControl ItemsSource="{Binding TreeMapItems}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas Background="White"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Rectangle Width="{Binding Width}" Height="{Binding Height}" Fill="{Binding Brush}" ToolTipService.ToolTip="{Binding Label}">
                <Rectangle.RenderTransform>
                    <TranslateTransform X="{Binding X}" Y="{Binding Y}"/>
                </Rectangle.RenderTransform>
            </Rectangle>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
于 2013-12-31T19:01:29.247 回答
0

替代方案:在演示之前创建“项目”期间,还有其他机会通过代码附加绑定。

ItemsControl.PrepareContainerForItemOverride http://msdn.microsoft.com/en-us/library/windows/apps/xaml/windows.ui.xaml.controls.itemscontrol.preparecontainerforitemoverride.aspx

ListViewBase.ContainerContentChanging http://msdn.microsoft.com/en-us/library/windows/apps/xaml/windows.ui.xaml.controls.listviewbase.containercontentchanging.aspx

于 2014-11-14T20:47:45.010 回答