1

I'm making an image gallery of sorts, and I'm currently loading the images into a grid dynamically via C#. If I shouldn't be using a grid to display the images, I'm more than willing to change it to a better-suited control, but it needs to be window-resizing-friendly.

When I resize the window, I want the following things to happen:

  • The images all stay the exact same size. They already fit into the grid slots while maintaining their aspect ratio
  • The grid spaces themselves are also not resized at all
  • The grid contains more or less rows/columns depending on how many can fit into the window.

This would mean that, if the window was resized to be very thin and very high, the grid would contain one column (or two, or however many are needed) and many rows to display the images in.

If it was very wide, but not high, then it would only have one (or two, or however many are needed) row(s) and many columns. Etc.

Not sure if it's needed but my code to display the images is:

        for (int i = 0; i < ImageGrid.RowDefinitions.Count; i++)
        {
            for (int j = 0; j < ImageGrid.ColumnDefinitions.Count; j++)
            {
                Image img = new Image();
                BitmapImage bitmap = new BitmapImage();

                using (var fs = new FileStream(path, FileMode.Open)) // open the image
                {
                    bitmap.BeginInit();
                    bitmap.StreamSource = fs;
                    bitmap.CacheOption = BitmapCacheOption.OnLoad;
                    bitmap.EndInit();
                }

                bitmap.Freeze(); // bitmap isn't properly cleaned up and memory leaks can occur if this isn't here

                img.Source = bitmap;

                img.Margin = new Thickness(10);

                img.Stretch = Stretch.Uniform;

                Grid.SetRow(img, i);
                Grid.SetColumn(img, j);

                ImageGrid.Children.Add(img);
            }
        }

And my XAML for the grid is:

    <Grid ShowGridLines="True" Background="DimGray">
        <Grid.ColumnDefinitions>
            <ColumnDefinition MinWidth="175" Width="0"/>
            <ColumnDefinition MinWidth="755" Width="Auto"/>
        </Grid.ColumnDefinitions>

        <Label Name="lblWinSize" Content="Width, Height" 
HorizontalAlignment="Left" VerticalAlignment="Bottom"/>
        <TextBox Name="txtnbox" Style="{StaticResource CustomTxtBox}" 
TextWrapping="NoWrap" Width="Auto" Height="25" VerticalAlignment="Top" 
Margin="10, 20, 10, 0"/>

        <Separator Style="{StaticResource VerticalSeparator}" 
HorizontalAlignment="Right" Height="Auto" Width="2" Margin="0,10,0,10"/>
        <CheckBox Style="{StaticResource CustomCheckBox}" 
HorizontalAlignment="Left" Margin="10,50,0,0" VerticalAlignment="Top"/>
        <Grid Name="ImageGrid" Grid.Column="1" Margin="10,10,0,10" 
ShowGridLines="True" Background="Gray">
            <!--this is the grid where the images would go-->
        </Grid>
    </Grid>

Sorry about the indentation with that XAML, I couldn't get it to format right.

The rows/columns are defined elsewhere in the code, but I don't think I need to paste that considering it'll be replaced.

Again, if some other control is better suited, I can change to that.

Athied
  • 25
  • 1
  • 5

3 Answers3

1

You will want to use a wrap panel.

<WrapPanel Orientation="Horizontal">
    <Image Width="50" Height="50" Source="bla.png" />
    <Image Width="50" Height="50" Source="bla.png" />
    <Image Width="50" Height="50" Source="bla.png" />
    <Image Width="50" Height="50" Source="bla.png" />
</WrapPanel>
aydjay
  • 858
  • 11
  • 25
  • This still doesn't work. I'm adding the images through C#, and they all display in one row (which is cut off by the window's edge) if the Orientation is horizontal, and in two rows if it's vertical. I cannot add the images through xaml. **Edit:** Removing the MinWidth and Width values from the second ColumnDefinition of the grid containing the WrapPanel seems to make the panel's contents dynamic horizontally, but they still get cut off by the bottom of the screen. – Athied Aug 07 '18 at 13:47
  • Have a look at this then: https://stackoverflow.com/questions/3131919/wrappanel-as-itempanel-for-itemscontrol#3131962 You will want to bind your itemscontrol and add your images programatically – aydjay Aug 08 '18 at 08:29
1

Use a WrapPanel to make layout of items fill the width of the window before adding a new row, inside of a ScrollViewer to allow scrolling vertically so the contents don't run out of viewable area.

<ScrollViewer>
  <WrapPanel HorizontalAlignment="Center">
    <!-- your items go here -->
  </WrapPanel>
</ScrollViewer>

If your images are being added dynamically, hopefully you're adding them to a collection that your view can bind to instead of directly adding them to the view in your codebehind... Use an ItemsControl and define your own template for items and container:

<ScrollViewer>
  <ItemsControl ItemsSource="{Binding Images}" HorizontalAlignment="Center">
    <ItemsControl.ItemTemplate>
      <DataTemplate>
        <Image Source="{Binding ...}" Height="150" Width="150"/>
      </DataTemplate>
    </ItemsControl.ItemTemplate>
    <ItemsControl.ItemsPanel>
      <ItemsPanelTemplate>
        <WrapPanel />
      </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
  </ItemsControl>
</ScrollViewer>
Nick
  • 4,556
  • 3
  • 29
  • 53
0

c# :

// here set number of images you want to parse
        int qtyOfImages = 10;

        for (int i = 0; i < qtyOfImages; i++) {
            Image img = new Image();
            BitmapImage bitmap = new BitmapImage();

            using (var fs = new FileStream(path, FileMode.Open)) // open the image
            {
                bitmap.BeginInit();
                bitmap.StreamSource = fs;
                bitmap.CacheOption = BitmapCacheOption.OnLoad;
                bitmap.EndInit();
            }

            bitmap.Freeze(); // bitmap isn't properly cleaned up and memory leaks can occur if this isn't here

            img.Source = bitmap;

            img.Margin = new Thickness(10);

            img.Stretch = Stretch.Uniform;

            //Grid.SetRow(img, i);
            //Grid.SetColumn(img, j);

            // set width and height so the images stay at the same size
            img.Width = 300;
            img.Height = 300;

            ImageGrid.Children.Add(img);
        }

while your xaml would be like:

 <Grid ShowGridLines="True" Background="DimGray">
        <Grid.ColumnDefinitions>
            <ColumnDefinition MinWidth="175" Width="0"/>
            <ColumnDefinition MinWidth="755" Width="Auto"/>
        </Grid.ColumnDefinitions>

        <Label Name="lblWinSize" Content="Width, Height" 
        HorizontalAlignment="Left" VerticalAlignment="Bottom"/>
        <TextBox Name="txtnbox"  Style="{StaticResource CustomTxtBox}"
            TextWrapping="NoWrap" Width="Auto" Height="25" VerticalAlignment="Top" 
            Margin="10, 20, 10, 0"/>

        <Separator Style="{StaticResource VerticalSeparator}" 
            HorizontalAlignment="Right" Height="Auto" Width="2" Margin="0,10,0,10"/>
        <CheckBox Style="{StaticResource CustomCheckBox}"
            HorizontalAlignment="Left" Margin="10,50,0,0" VerticalAlignment="Top"/>
        <!--<Grid Name="ImageGrid" Grid.Column="1" Margin="10,10,0,10" 
                    ShowGridLines="True" Background="Gray">
                --><!--this is the grid where the images would go--><!--
            </Grid>-->


        <!-- set size of wrap panel to your window acutal width -->
        <WrapPanel Orientation="Horizontal" Name="ImageGrid" Width="{Binding ElementName=Window, Path=ActualWidth}">

        </WrapPanel>

    </Grid>

dont forget to put Name="Window" at your window for this code to work

Hope that helps

  • Thanks, this worked. Wrapped the WrapPanel in a Scrollviewer like @Nick mentioned and changed a couple other things and it works great now. Honestly, I'd totally forgotten WrapPanels existed. Was stupid but I'll leave this post up so that other people having my problem see it. Here's the final XAML for the image display: https://pastebin.com/m1JpUfFU – Athied Aug 08 '18 at 13:09