使用ItemsControl时,如果将ItemsControl.ItemsPanel设置为Canvas,则会出现ContenPresenter并破坏子元素上的Canvas属性 [WPF]

16

我正在使用一个ItemsControl,其中ItemsPanel设置为Canvas(有关更多背景信息,请参见问题)。 ItemsControl按照我的要求执行,并且在将子元素手动放入ItemsControl.Items时非常有效:

<ItemsControl>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas IsItemsHost="True" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.Items>
        <Button Canvas.Left="500" Content="Button Text" />
    </ItemsControl.Items>
</ItemsControl>

注意按钮上的Canvas.Left属性。这很好用,按钮距离ItemsControl左侧500像素。太棒了!但是,当我将ItemsSource绑定到List时,Canvas.left没有任何效果:
<ItemsControl ItemsSource="{Binding Elements}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas IsItemsHost="True" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button Canvas.Left="500" Content="Button Text" />
        </DataTemplate>     
    </ItemsControl.ItemTemplate>
</ItemsControl> 

在运行时检查应用程序时,我看到了一个区别。容器ContentPresenter已添加在Canvas和按钮之间。

我如何在ContentPresenter本身上设置Canvas.Left属性?还是有其他方法可以解决这个问题?

感谢大家!

3个回答

25

可以使用ItemContainerStyle设置Canvas.Left属性:

<ItemsControl ItemsSource="{Binding Elements}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas IsItemsHost="True" />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Button Content="Button Text" />
            </DataTemplate>     
        </ItemsControl.ItemTemplate>
    <ItemsControl.ItemContainerStyle>
        <Style>
             <Setter Property="Canvas.Left" Value="500" />
        </Style>
    </ItemsControl.ItemContainerStyle>
</ItemsControl>

1
你也可以在ItemContainerStyle中绑定值,并且它将使用与DataTemplate相同的项作为源。 :-) - Russell Giddings
今天你是我的英雄。 谢谢。 - Peter pete

4
我脑海中有几个解决方案:
  1. 使用布局/渲染转换而不是附加属性。
  2. 使用外边距代替附加属性。
  3. 从ItemsControl派生,并重写如何生成子容器的行为。(GetContainerForItemOverride,IsItemItsOwnContainerOverride)。这篇文章很好地解释了它的工作原理:http://drwpf.com/blog/2008/07/20/itemscontrol-g-is-for-generator/

2
没有“Canvas”属性,因此您所做的是对托管控件进行相对调用,但由于项目和画布位于不同的模板中,因此没有直接链接,因此在运行时之前,.Canvas.Left是没有意义的。
因此,您的方法找不到要设置的左侧位置,因此丢失了更改。
但是,Setters仅在运行时实现。
<Setter Property="Canvas.Left" Value="500" /> 

只有在生成对象后才能运行,并且具有相对关系。

否则,您可以使用边距,它属于按钮对象,但仅在运行时解释。


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