代码之家  ›  专栏  ›  技术社区  ›  Rob Perkins

当有一个复杂的数据模板隐藏基于触发器的显示元素时,我的ListView或ListBox控件的大小不会缩小?

  •  3
  • Rob Perkins  · 技术社区  · 16 年前

    我有一个listview元素,每个listviewitem都有一个数据模板,定义如下。运行时,ListView的高度不会折叠到视图中的项目上,这是不需要的行为:

    <datatemplate x:key=“licenseitemtemplate”>
    格栅& GT;
    <grid.rowdefinitions>
    <rowdefinition height=“自动”/>
    <rowdefinition height=“自动”/>
    </grid.rowdefinitions>
    <textblock grid.row=“0”text=“绑定公司”></textblock>
    <grid grid.row=“1”style=“StaticResource hiddenWhennotSelectedStyle”>
    <grid.rowdefinitions>
    <行定义/>
    </grid.rowdefinitions>
    <button grid.row=“0”>单击它</button>
    和/格栅& GT;
    和/格栅& GT;
    </datatemplate>
    < /代码> 
    
    

    外部网格的第二行应用了类似这样的样式。样式的目的是公开所选数据项的详细视图:

    <style targettype=“x:type grid”x:key=“hiddenwhennotselectedstyle”>
    <style.triggers>
    DataTrigger
    binding=“binding path=isselected,
    相对震源={
    相对资源
    模式=findancestor,
    ancestorType=x:类型ListViewItem
    }
    }
    value=“false”>
    <setter property=“grid.visibility”value=“collapsed”/>
    </datatrigger>
    DataTrigger
    binding=“binding path=isselected,
    相对震源={
    相对资源
    模式=findancestor,
    ancestorType=x:类型ListViewItem
    }
    }
    value=“真”>
    安装工
    属性=“grid.visibility”
    值=“可见”
    /gt;
    </datatrigger>
    </style.triggers>
    &风格/风格;
    < /代码> 
    
    

    ListView呈现如下:

    当没有选择任何元素时,所需的外观是:

    …当然,当通过选择使第二个网格可见时,使用ListView的高度调整以适应附加内容。我能做些什么来获得想要的行为?

    <DataTemplate x:Key="LicenseItemTemplate">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"  />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <TextBlock Grid.Row="0" Text="{Binding company}"></TextBlock>
            <Grid Grid.Row="1" Style="{StaticResource HiddenWhenNotSelectedStyle}">
                <Grid.RowDefinitions>
                    <RowDefinition />
                </Grid.RowDefinitions>
                <Button Grid.Row="0">ClickIt</Button>
            </Grid>
        </Grid>
    </DataTemplate>
    

    外部网格的第二行应用了类似这样的样式。样式的目的是公开所选数据项的详细视图:

    <Style TargetType="{x:Type Grid}" x:Key="HiddenWhenNotSelectedStyle" >
        <Style.Triggers>
            <DataTrigger
                Binding="{Binding Path=IsSelected, 
                            RelativeSource={
                            RelativeSource 
                            Mode=FindAncestor, 
                            AncestorType={x:Type ListViewItem}
                            }
                            }" 
                Value="False">
                <Setter Property="Grid.Visibility" Value="Collapsed" />
            </DataTrigger>
            <DataTrigger
                Binding="{Binding Path=IsSelected, 
                            RelativeSource={
                            RelativeSource 
                            Mode=FindAncestor, 
                            AncestorType={x:Type ListViewItem}
                            }
                            }" 
                Value="True">
                <Setter
                    Property="Grid.Visibility"
                    Value="Visible"
                />
            </DataTrigger>
        </Style.Triggers>
    </Style>
    

    ListView呈现如下: Height of ListView is twice what it should be.

    当没有选择任何元素时,所需的外观是: Height of ListView is collapsed to list items.

    …当然,当通过选择使第二个网格可见时,通过调整ListView的高度来适应额外的内容。我能做些什么来获得想要的行为?

    2 回复  |  直到 12 年前
        1
  •  15
  •   Rob Perkins    16 年前

    在与TechEd的WPF人员讨论这个问题时,我向一位微软员工展示了这个问题。他心神不宁。

    我们下载了一个工具来询问WPF布局,并在ListView中将容器标识为“虚拟化堆栈面板”元素。

    在随后的一封电子邮件中,他写道:“这是虚拟化stackpanel的错误。我打开了一个关于它的bug。希望它可以在将来的版本中修复。只要您不需要ListView来虚拟化其内容,现在的解决方法(使用StackPanel)应该是不错的。

    这个bug涉及到vsp_的度量算法中的一个步骤,它可以记住有史以来发现的最大大小,并强制所有未来的度量调用报告一个至少同样大的大小。在您的例子中,VSP最初是在触发任何触发器之前测量的,因此它计算大小时好像所有内容都是可见的。当触发器触发并折叠按钮时,度量算法计算正确(小)的大小,但随后强制结果再次变大。该注释说明了在滚动时避免不必要的重新布局,但即使没有滚动,代码也在运行。”

    解决方法包括使用以下代码重新模板化ListView:

    <ListView.ItemsPanel>
      <ItemsPanelTemplate>
        <StackPanel/>
      </ItemsPanelTemplate>
    </ListView.ItemsPanel>
    

    这导致了列表行为按需工作,但它的缺点是没有virtualizingstackpanel的内存管理功能。对于我来说,这是适当的;列表项一次不会超过2000个左右。

        2
  •  0
  •   compozer    16 年前

    尝试添加第三行定义为

    <RowDefinition Height="*" />
    

    <Grid.RowDefinitions> 第一个网格。