I'm pretty sure the answer is "not easily".
Here's an idea that seems to work but it's kind of clunky:
Throw your StackPanel into a UserControl (UserControl1
in the example below).
Place two copies of this UserControl into a container (a Grid in the example below).
a. Align the first copy top/left so that it remains at its default size. This copy is strictly for measurement purposes and should have its Visibility set to Hidden.
b. Place the second copy inside a Viewbox. This copy is the one the user will actually see.
Use a MultiBinding with a MultiValueConverter to adjust the width of the second UserControl so that it has the correct aspect ratio before it gets expanded by the Viewbox.
Here's the markup:
<Grid>
<local:UserControl1 x:Name="RawControl" HorizontalAlignment="Left" VerticalAlignment="Top" Visibility="Hidden" />
<Viewbox>
<local:UserControl1>
<local:UserControl1.Width>
<MultiBinding Converter="{StaticResource WidthAdjuster}">
<Binding ElementName="RawControl" Path="ActualHeight" />
<Binding RelativeSource="{RelativeSource AncestorType=Grid}" Path="ActualWidth" />
<Binding RelativeSource="{RelativeSource AncestorType=Grid}" Path="ActualHeight" />
</MultiBinding>
</local:UserControl1.Width>
</local:UserControl1>
</Viewbox>
</Grid>
Here's the MultiValueConverter
public class WidthAdjuster : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
var rawHeight = (double)values[0];
var containerWidth = (double)values[1];
var containerHeight = (double)values[2];
var ratio = containerWidth / containerHeight;
return rawHeight * ratio;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Result for 525 x 350 container
