Dynamically change columns number in uniformgrid inside listbox dependent on context

865 views Asked by At

I have a listbox where I want to set columns depends on context (image size). So if I have bigger images, then I want fewer columns. If the columns attribute is not set, then it works ok, but the stretch is too big if I have very wide images. If I set minWidth or minHeight of the image, not always working ok because of different image sizes (many empty spaces added in wide images). So my next idea is to programmatically set the number of columns to depend on image size. Maybe with binding, but I don't have an idea of how to apply this to code.

<ListBox SelectionMode="Multiple" Grid.Column="0" x:Name="lvBox" ScrollViewer.HorizontalScrollBarVisibility="Disabled" VerticalAlignment="Top">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <UniformGrid Columns="2" HorizontalAlignment="Stretch"/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ListBox.ItemContainerStyle>
                    <Style TargetType="{x:Type ListBoxItem}">
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="ListBoxItem">
                                    <Border Name="Border" Padding="2" SnapsToDevicePixels="true" Background="White" Margin="0">
                                        <ContentPresenter/>
                                    </Border>
                                    <ControlTemplate.Triggers>
                                        <Trigger Property="IsSelected" Value="true">
                                            <Setter TargetName="Border" Property="Background" Value="LightBlue"/>
                                        </Trigger>
                                    </ControlTemplate.Triggers>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </ListBox.ItemContainerStyle>
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Vertical" HorizontalAlignment="Stretch">
                            <Image Name="imageView" Source="{Binding ImageData}" HorizontalAlignment="Stretch" VerticalAlignment="Top" Stretch="UniformToFill" />
                            <TextBlock Text="{Binding TimeStamp}" HorizontalAlignment="Stretch" VerticalAlignment="Bottom"/>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

Here is problem, where columns atribute in uniformgrid is not set and images are wide. Images are too small (too much columns).

Wide Images

And here is problem of normal images, and columns are set directly to 2. Images are too big (not enough columns).

enter image description here

Any idea how to solve this problem? How limit the stretch without hardcode setting minWidth or minHeight or how set in C# columns number depends of image size.

1

There are 1 answers

0
Nejc Galof On BEST ANSWER

I found a solution that works for me. I add in ItemsPanelTemplate binding like this:

<ItemsPanelTemplate>
  <UniformGrid Columns="{Binding Path=Cols}" HorizontalAlignment="Stretch"/>
</ItemsPanelTemplate>

And I use Property Change Notification. Add INotifyPropertyChanged to class and here is the rest of the code:

private int _cols = 1;
public bool Cols
{
  get => _cols;
}

public event PropertyChangedEventHandler PropertyChanged;
void RaisePropertyChanged(string propertyName)
{
  PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

RaisePropertyChanged(nameof(Cols));

When I calculate number of columns, I set _cols and then call RaisePropertyChanged(nameof(Cols));