XAML itemscontrol:contentpresenter 可见性不反映每个拥有的项目

XAML itemscontrol: contentpresenter visibility doesn't reflect each owned item

在 ItemsControl 中,项目位于 ContentPresenter 中,因此如果项目具有 Visibility='collapsed',其 ContentPresenter 仍然具有 Visibility='Visible'... (Here 解释了此行为)

因此这 2 个示例显示的结果不同:

这符合我的预期:

<UniformGrid Columns="1">
    <Button Content="0"/>
    <Button Content="1"/>
    <Button Content="2" Visibility="Collapsed"/>
    <Button Content="3"/>
</UniformGrid>

这不像我预期的那样工作(UniformGrid 为第三个按钮保留 space,如果它被折叠):

<ItemsControl>
    <ItemsControl.ItemsSource>
        <x:Array Type="{x:Type System:Int32}">
            <System:Int32>0</System:Int32>
            <System:Int32>1</System:Int32>
            <System:Int32>2</System:Int32>
            <System:Int32>3</System:Int32>
        </x:Array>
    </ItemsControl.ItemsSource>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid Columns="1"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button Visibility="{Binding ., Converter={StaticResource CalculatorConverter}, ConverterParameter=IIF(\{0\}\=2\,\'Collapsed\'\,\'Visible\')}" Content="{Binding .}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

有人遇到过这个问题吗?有解决方法吗?

这是预期的行为,因为该按钮不是 UniformGrid 的直接子项。相反,ItemsControl 将使用您定义的 DataTemplate 模板化的 ContentPresenter 添加到 UniformGrid。所以基本上视觉树类似于:1

<UniformGrid>
    ....
    <ContentPresenter>
        <Button Visibility="Collapsed" />
    </ContentPresenter>
    ....
</UniformGrid>

我认为这清楚地说明了为什么即使按钮已折叠,网格中的 space 也会被保留。当然,要补救,您应该折叠 ContentPresenter。可以通过使用 ItemsControl.ItemContainerStyle 属性:

来实现
<ItemsControl>
    <ItemsControl.ItemContainerStyle>
        <Style TargetType="{x:Type ContentPresenter}">
            <Setter Property="Visiblity" Value="{Binding ., Converter=...}" />
        </Style>
    </ItemsControl.ItemContainerStyle>
    ...
</ItemsControl>

1 提供的代码只是可视化树的示例,不是有效的 WPF XAML.