如何在WinRT中的ItemContainerStyle中进行绑定?

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>

我已验证ContentPresenter具有正确的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时,出现了绑定错误,说该属性在类型Setter上不存在!这里有点太字面了。

我还尝试了TemplateBinding,但我从未真正理解它应该用于什么,而且我得到了一些难以理解的COM错误(欢迎来到WinRT,一个巨大的技术倒退)。

我该如何才能使绑定正常工作(是否有其他可以使用的Binding选项来强制它正常工作?),或者允许我的ItemsContainer中的项目根据集合项属性的数据绑定在Canvas上任意位置?

3个回答

14

在Setter上不支持绑定。我认为Silverlight只有在版本5中才支持它们,如果有的话。关于解决方法,您可以查看我的旧文章这里。基本上,您需要定义一个附加依赖属性来为您设置绑定。


3
这是一个相当聪明的技巧,在WinRT中确实有效,虽然语法有所不同;你必须使用new Binding { Path = new PropertyPath(newValue) }而不是new Binding(newValue)。我认为我将重命名附加属性以使用PathBindingPath结尾,这样XAML更容易理解。总的来说,这是一个好的、可行的解决方案。谢谢! - Joe White
安装最新版本win8.9200(8月15日之后)后,似乎<Setter Property="Canvas.Left" Value="200"/>也不起作用了!我想我会放弃在图形应用程序中进行绑定 :( 因为这对我来说是一大步退步。 - Stefano.net
@Filip Skakun: (+1) 对 (Canvas.Left) 的赞同是为什么呢? - HCL
1
我认为这是因为它是一个附加属性? - Filip Skakun

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>

1
尽管这是一个非常旧的帖子,但您的方法在某种程度上对我起作用了,唯一的问题是按钮正在Windows Phone 8.1中超出画布。 <ItemsControl.ItemTemplate> <DataTemplate> <Button Height="{Binding Height}" Width="{Binding Width}" Content="{Binding Content}"> <Button.RenderTransform> <TranslateTransform X="{Binding TopLeftX}" Y="{Binding TopLeftY}"/> </Button.RenderTransform> </Button> </DataTemplate> </ItemsControl.ItemTemplate>你知道哪里出了问题吗? - Debhere

0

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