The WPF viewbox is an automatically resizable/redimensionable Windows Presentation Foundation layout control. It is capable of resizing to fill the available area, automatically adjusting the size of the child (the control which it contains, and which is displayed) and the sizes and relative positions of the elements which make up the child as it does so. It automatically adjusts coordinates for the change in size, so that a set of coordinates given in pixels in the original size, for example, will still describe the same relative location in the resized child control. Copy from https://blog.udemy.com/wpf-viewbox/
//xaml <Window x:Class="WpfApp105.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:WpfApp105" mc:Ignorable="d" WindowState="Maximized" Title="{Binding ImageUrlRelative,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Height="450" Width="800"> <Grid x:Name="grid"> <Grid.ColumnDefinitions> <ColumnDefinition Width="300"/> <ColumnDefinition/> </Grid.ColumnDefinitions> <ListBox x:Name="lbx" Grid.Column="0" ItemsSource="{Binding ImgsList,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" SelectionMode="Extended" SelectionChanged="ListBox_SelectionChanged" > <ListBox.ItemTemplate> <DataTemplate> <StackPanel Height="200"> <Image Source="{Binding Content,RelativeSource={RelativeSource AncestorType=ListBoxItem}}" Stretch="Uniform" Width="200" Height="200"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> <Viewbox Grid.Column="1" CacheMode="BitmapCache" RenderOptions.BitmapScalingMode="HighQuality"> <Image x:Name="img" Source="{Binding ImgUrl,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Stretch="UniformToFill" MouseWheel="img_MouseWheel" > <Image.LayoutTransform> <ScaleTransform ScaleX="{Binding ScaleValue,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" ScaleY="{Binding ScaleValue,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"> </ScaleTransform> </Image.LayoutTransform> </Image> </Viewbox> </Grid> </Window> //xaml.cs using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace WpfApp105 { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window,INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string propName) { var handler = PropertyChanged; if(handler!=null) { handler?.Invoke(this, new PropertyChangedEventArgs(propName)); } } private ObservableCollection<string> imgsList = new ObservableCollection<string>(); public ObservableCollection<string> ImgsList { get { return imgsList; } set { if(value != imgsList) { imgsList = value; OnPropertyChanged(nameof(ImgsList)); } } } private string imgUrl; public string ImgUrl { get { return imgUrl; } set { if(value!=imgUrl) { imgUrl = value; OnPropertyChanged(nameof(ImgUrl)); ImageUrlRelative=System.IO.Path.GetFileName(ImgUrl); } } } private double scaleValue = 1.0; public double ScaleValue { get { return scaleValue; } set { if(value != scaleValue) { scaleValue = value; OnPropertyChanged(nameof(ScaleValue)); } } } private string imgUrlRelative = string.Empty; public string ImageUrlRelative { get { return imgUrlRelative; } set { if(value!=imgUrlRelative) { imgUrlRelative = value; OnPropertyChanged(nameof(ImageUrlRelative)); } } } public MainWindow() { InitializeComponent(); InitData(); this.DataContext = this; this.Loaded += MainWindow_Loaded; } private void MainWindow_Loaded(object sender, RoutedEventArgs e) { img.Width = grid.ColumnDefinitions[1].ActualWidth; } private void InitData() { var dir = @"..\..\Images"; string fullDir = System.IO.Path.GetFullPath(dir); if(System.IO.Directory.Exists(fullDir)) { var allImgs = System.IO.Directory.GetFiles(fullDir); ImgsList = new ObservableCollection<string>(allImgs); ImgUrl=ImgsList.FirstOrDefault(); ImageUrlRelative = System.IO.Path.GetFileName(ImgUrl); } } private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { ScaleValue = 1; var selectedItems = lbx.SelectedItems; if(selectedItems!=null && selectedItems.Count > 0) { var firstItem = selectedItems[0]; ImgUrl=firstItem.ToString(); } } private void img_MouseWheel(object sender, MouseWheelEventArgs e) { if(e.Delta > 0) { ScaleValue *= 1.2; } else { ScaleValue /= 1.2; } } } }