I'm having trouble with a Grid
when the parent is a Viewbox
.
I have an image selector in WPF consisting of a two column Grid
.
- The right column is a
ListBox
of thumbnails taking 25% of the entire width of the grid. - When a thumbnail is selected, it is presented in the left column taking up the remaining space.
The mail image should stretch keeping its aspect ratio until one of the dimensions reaches the either the column width or the grid's height.
I'd like to be able to scale the entire image selector uniformly so I surrounded it in a Viewbox
.
However, after adding the ViewBox
it seems to have broken Grid
and ListBox
behaviours:
- Clicking on the second image selects the wrong image
- The grid column ratios aren't respected when images of different aspect ratios are selected. Eg if I choose a thin image like the first, then the columns are more like 50/50 ratio.
I'm not tied to having Viewbox
or Grid
controls, I just would like the functionality I get from the grid and ListBox
when the Viewbox
isn't there and add uniform scaling of the grid and its children.
I've extracted the relevant code below:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace WpfViewBox
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Images = new List<ImageSource>()
{
new BitmapImage(new Uri("https://images.unsplash.com/photo-1648720666508-102320ea1c11?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwxMHx8fGVufDB8fHx8")),
new BitmapImage(new Uri("https://images.unsplash.com/photo-1648672231811-4b3b3642f2e0?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwzOXx8fGVufDB8fHx8")),
new BitmapImage(new Uri( "https://images.unsplash.com/photo-1648687735004-acb0bb16c8d9?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwxNTB8fHxlbnwwfHx8fA%3D%3")),
};
ImageListBox.SelectedIndex = 0;
}
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
MainImage.Source = (ImageSource)ImageListBox.SelectedItem;
}
public IEnumerable Images { get; set; }
}
}
<Window x:Class="WpfViewBox.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfViewBox"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Viewbox>
<Grid Margin="8" MaxHeight="240" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width=".25*" />
</Grid.ColumnDefinitions>
<Image Grid.Column="0"
x:Name="MainImage"
Height="240"
Stretch="Uniform"
StretchDirection="Both"/>
<ListBox x:Name="ImageListBox"
Grid.Column="1"
SelectionChanged="ListBox_SelectionChanged"
ItemsSource="{Binding Images, RelativeSource={RelativeSource AncestorType=Window}}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}"
HorizontalAlignment="Center"
Height="120"
Stretch="Uniform"
StretchDirection="Both"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Viewbox>
</Window>
Note: the vertical scrollbar is hidden, but you can either use the arrow keys to move one at a time or the mouse wheel to scroll multiple (depending on your system settings).