Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF - Hide items in ItemControl -> UniformGrid from taking up UI space based on databinding

Databound to an ObservableCollection, I am filling an ItemsControl with Buttons. I am using UniformGrid to help evenly spread things out whether there are 5 or 5000 objects in the ObservableCollection.

Desire: After the user searches/filters the ObservableCollection, I would like to update an IsVisible property on items to show/hide them... while also consolidating the space.

Rationale: I figured, performance wise, updating a property would be better than doing a Clear() and loop to re-add the filtered items back to the databound ObservableCollection.

Problem: While the current implementation (code below) does visibly hide the buttons, the space they take up still is present regardless of which Visibility property I try to use.

Disclaimer: I am open to more than just simply "fixing" my current code. For example, if a viable solution does not use UniformGrid for example but still achieves a sustainable result, I can probably use it! The same is true on the ViewModel side.

<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>

Update: I did not simply copy and paste the entire answer.

  1. In the code above, at Button, inside of the DataTemplate, I removed the Visibility line.
  2. I only added the following code:

            <ItemsControl.ItemContainerStyle>
                <Style TargetType="ContentPresenter">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding IsVisible}" Value="False">
                            <Setter Property="Visibility" Value="Collapsed" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </ItemsControl.ItemContainerStyle>
    
like image 969
Steven_BDawg Avatar asked Jun 02 '19 20:06

Steven_BDawg


1 Answers

It has no effect to set the Visibility of the Button in the DataTemplate. You should instead set the Visibility of the item container, i.e. the ContentPresenter that displays the individual items.

You would achieve that by setting the ItemContainerStyle of the ItemsControl to a Style with a Setter that binds the Visibility property, or with a DataTrigger instead of a Binding with 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>
like image 84
Clemens Avatar answered Oct 23 '22 22:10

Clemens