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

Joe*_*ite 24 binding itemscontrol itemcontainerstyle windows-runtime winrt-xaml

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

由于ItemsControl将您的ItemTemplate内容包装在另一个UI元素(在WinRT的情况下为ContentPresenter)中,并且它是直接放置在items面板中的那些包装器/容器元素,因此必须在这些容器上设置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>
Run Code Online (Sandbox Code Playgroud)

但是当我在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>
Run Code Online (Sandbox Code Playgroud)

我已经验证了ContentPresenters确实有正确的DataContext(即集合项,而不是集合本身或其他时髦的东西),所以你认为这些绑定可以正常工作.但他们似乎甚至没有得到评估.如果我在其他地方放置了一个错误的绑定,并运行调试版本,我会在调试器的Output窗口中看到绑定错误; 但是如果我在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>
Run Code Online (Sandbox Code Playgroud)

我已经尝试了一些更具异国情调的选项Binding- 特别是RelativeSource.当我使用时RelativeSource TemplatedParent,无所事事的行为没有改变.但是,当我使用时RelativeSource Self,我确实得到了一个绑定错误,说该属性在类型上不存在Setter!那里的Self字面意义太过分了.

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

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

Fil*_*kun 14

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

  • 这是一个非常聪明的黑客,它确实在WinRT中有效 - 尽管语法不同; 你必须做`new Binding {Path = new PropertyPath(newValue)}`而不是`new Binding(newValue)`.我还认为我将重命名附加属性以`Path`或`BindingPath`结束,因此XAML更容易遵循.但总而言之,这是一个好的,可行的解决方案.谢谢! (3认同)

Jas*_*son 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>
Run Code Online (Sandbox Code Playgroud)