【问题标题】:WPF - Hide items in ItemControl -> UniformGrid from taking up UI space based on databindingWPF - 隐藏 ItemControl -> UniformGrid 中的项目,以免占用基于数据绑定的 UI 空间
【发布时间】:2019-10-18 11:46:36
【问题描述】:

数据绑定到ObservableCollection,我正在用Buttons 填充ItemsControl。我正在使用UniformGrid 来帮助均匀分布ObservableCollection 中是否有5 个或5000 个对象。

愿望:在用户搜索/过滤ObservableCollection 后,我想更新项目上的IsVisible 属性以显示/隐藏它们......同时也巩固空间。

理由:我认为,就性能而言,更新属性比执行Clear() 并循环将过滤后的项目重新添加回数据绑定ObservableCollection 更好。

问题:虽然当前的实现(下面的代码)确实隐藏了按钮,但无论我尝试使用哪个 Visibility 属性,它们占用的空间仍然存在。

免责声明:我愿意接受的不仅仅是简单地“修复”我当前的代码。例如,如果一个可行的解决方案不使用UniformGrid,但仍能达到可持续的结果,我可能会使用它! ViewModel 端也是如此。

<ItemsControl Name="ItemsList"
            Width="Auto"
            HorizontalContentAlignment="Left"
            ItemsSource="{Binding ItemsVM.WorkList}"
            ScrollViewer.CanContentScroll="True" VirtualizingStackPanel.IsVirtualizing="true"
            VirtualizingStackPanel.VirtualizationMode="Standard"
            >
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <UniformGrid Columns="5" />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>

            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Button
                        Width="250" Height="50"
                        FontSize="18" FontWeight="Bold"
                        Background="{Binding TextColor, Converter={StaticResource TextToColorConvert}, UpdateSourceTrigger=PropertyChanged}"
                        Margin="1,1,1,1" HorizontalAlignment="Center" VerticalAlignment="Center"
                        BorderBrush="WhiteSmoke" BorderThickness="0" Click="workNumSelect"
                        Content="{Binding Workload.WorkNum}"
                        Cursor="Hand" Opacity=".8"
                        Visibility="{Binding IsVisible, Converter={StaticResource BoolToCollapsedVisConvert}, UpdateSourceTrigger=PropertyChanged}"
                        />
                </DataTemplate>
            </ItemsControl.ItemTemplate>
            <ItemsControl.Template>
                <ControlTemplate TargetType="ItemsControl">
                    <ScrollViewer Width="Auto" VerticalScrollBarVisibility="Visible">
                        <ItemsPresenter />
                    </ScrollViewer>
                </ControlTemplate>
            </ItemsControl.Template>
        </ItemsControl>

更新: 我没有简单地复制和粘贴整个答案。

  1. 在上面的代码中,在ButtonDataTemplate 内部,我删除了Visibility 行。
  2. 我只添加了以下代码:

            <ItemsControl.ItemContainerStyle>
                <Style TargetType="ContentPresenter">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding IsVisible}" Value="False">
                            <Setter Property="Visibility" Value="Collapsed" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </ItemsControl.ItemContainerStyle>
    

【问题讨论】:

  • 无法理解问题,但似乎没有双向绑定
  • 如果屏幕上有 10 个按钮并且用户(在另一个未列出的字段中)将按钮过滤到 4 个,则其中 6 个按钮将消失。但是,分配给这 6 个按钮的空间仍然被占用。
  • 好的,我明白了。您需要为空的转换器调试..
  • 换句话说,如果我硬编码 10 个按钮,六个折叠按钮不会占用空间。
  • 请注意,在 OneWay 绑定(如背景和可见性)上设置 UpdateSourceTrigger=PropertyChanged 无效。 UpdateSourceTrigger 仅影响 TwoWay 或 OneWayToSource Bindings,与 PropertyChanged 事件无关。

标签: c# wpf mvvm observablecollection datatemplate


【解决方案1】:

在 DataTemplate 中设置 Button 的 Visibility 无效。您应该设置项目容器的可见性,即显示单个项目的ContentPresenter

您可以通过将 ItemsControl 的 ItemContainerStyle 设置为具有绑定 Visibility 属性的 Setter 的 Style 或使用 DataTrigger 而不是与 Converter 绑定来实现此目的。

<ItemsControl ItemsSource="{Binding}">
    <ItemsControl.Template>
        <ControlTemplate TargetType="ItemsControl">
            <ScrollViewer VerticalScrollBarVisibility="Visible">
                <ItemsPresenter />
            </ScrollViewer>
        </ControlTemplate>
    </ItemsControl.Template>

    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid Columns="5" VerticalAlignment="Top"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button ... />
        </DataTemplate>
    </ItemsControl.ItemTemplate>

    <ItemsControl.ItemContainerStyle>
        <Style TargetType="ContentPresenter">
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsVisible}" Value="False">
                    <Setter Property="Visibility" Value="Collapsed"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ItemsControl.ItemContainerStyle>
</ItemsControl>

【讨论】:

  • 能否告诉我为什么它对可见性没有影响,谢谢
  • @AvinashReddy 因为容器仍然存在,即使其 ContentTemplate 中的元素已折叠。
  • @AvinashReddy 就像给了你 10 张纸,有人告诉你要把每张纸折成什么……除了那个人故意告诉你不要对其中的 6 张纸做任何事情。你还有10张纸! Clemens:很好的解释和很好的解决方案,我认为可以应用于很多事情。我不知道 ItemContainerStyle 可以以这种方式使用!谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-04
  • 2011-12-04
  • 2019-06-13
  • 1970-01-01
相关资源
最近更新 更多