Page 1 of 1

Setting the Stretch of an Image element contained in a DataTemplate in UserControl.Resources

Posted: 10 Mar 2020, 22:27
by jpattersonCSpeed
Hi,

I am trying to view an image in 2 different display modes, one where it is viewed full screen, and one where it is smaller and has information about the image displayed to the right. The user views an image out of a list, which is implemented via a ListView element, and each image index is displayed using DataTemplates in UserControl.Resources for the screen. I also have Styles for the ListView and for each item that the ListView displays. Each index of the ListView has a data context of an ImageModel. An instance of ImageModel contains properties consisting of IsDetailedView to determine which view to display, MainBitmapSource to display the image, ImageStretch to dictate a stretch type, ImageTransformGroup to dictate some transforms that are being applied, and Margins to affect the margins of the border wrapping around the Image element.

See code for further details:
<UserControl ... >
    <UserControl.Resources>
        <Style x:Key="ListViewStyle" TargetType="{x:Type ListView}">
            <Setter Property="Grid.IsSharedSizeScope" Value="True"/>
            <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
            <Setter Property="BorderBrush" Value="{x:Null}"/>
            <Setter Property="BorderThickness" Value="0"/>
            <Setter Property="ItemsPanel">
                <Setter.Value>
                    <ItemsPanelTemplate>
                        <VirtualizingStackPanel />
                    </ItemsPanelTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ListView}">
                        <ItemsPresenter>
                        </ItemsPresenter>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

        <Style x:Key="ListBoxItemStyle" TargetType="{x:Type ListBoxItem}">
            <Setter Property="FocusVisualStyle" Value="{x:Null}" />
            <Setter Property="BorderThickness" Value="0" />
            <Setter Property="IsEnabled" Value="False"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ListBoxItem}">
                        <ContentPresenter HorizontalAlignment="Stretch" VerticalAlignment="Stretch" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

        <DataTemplate x:Key="fullScreenTemplate">
            <!-- DataContext here is still ImageModel -->
            <Border BorderBrush="Black" BorderThickness="0" Margin="{Binding Path=Margins}">
                <Image Source="{Binding Path=MainBitmapSource}" 
                       Stretch="{Binding Path=ImageStretch}"
                       RenderTransform="{Binding Path=ImageTransformGroup}"
                       SizeChanged="OnSizeChanged"/>
            </Border>
        </DataTemplate>

        <DataTemplate x:Key="detailScreenTemplate">
            <!-- DataContext here is still ImageModel -->
            <Grid>
                <Grid.ColumnDefinitions>
                    <!-- In a detailed view, the details are given a static 326px
                         on the right side and the image gets the rest -->
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="326"/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <!-- 45px for top display, 100px for bottom display, rest for content -->
                    <RowDefinition Height="45"/>
                    <RowDefinition Height="*"/>
                    <RowDefinition Height="100"/>
                </Grid.RowDefinitions>
                <Border Grid.Column="0" Grid.Row="1" BorderBrush="Black" BorderThickness="0" Margin="{Binding Path=Margins}">
                    <Image Source="{Binding Path=MainBitmapSource}" 
                           Stretch="{Binding Path=ImageStretch}"
                           RenderTransform="{Binding Path=ImageTransformGroup}"
                           SizeChanged="OnSizeChanged"/>
                </Border>

                <!-- Info display xaml is omitted, but is contained in Grid.Row="1" and Grid.Column="1" -->
            </Grid>
        </DataTemplate>

        <DataTemplate x:Key="ImageBaseTemplate">
            <!-- DataContext here is ImageModel -->
            <ContentControl Name="Content" Content="{Binding}"/>
            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding Path=IsDetailedView}" Value="False">
                    <Setter TargetName="Content" Property="ContentTemplate" Value="{StaticResource fullScreenTemplate}"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding Path=IsDetailedView}" Value="True">
                    <Setter TargetName="Content" Property="ContentTemplate" Value="{StaticResource detailScreenTemplate}"/>
                </DataTrigger>
            </DataTemplate.Triggers>
        </DataTemplate>
    </UserControl.Resources>
    
    <ListView Name="ListView" ItemsSource="{Binding Path=ImageModelList}"
              Style="{StaticResource ListViewStyle}"
              Background="Transparent"
              VerticalAlignment="Bottom"
              Margin="0,0,0,0"
              ItemTemplate="{StaticResource ImageBaseTemplate}"
              ItemContainerStyle="{StaticResource ListBoxItemStyle}"
              KeyDown="KeyDownHandler">
    </ListView>
</UserControl>
I would like the current image being displayed to have a stretch property value of Uniform, but always observe UniformToFit even though the ImageModel reports Uniform. I have also tried hardcoding the Stretch property to Uniform, but do not see any change. Both view templates exhibit this behavior.

Am I doing something wrong in my XAML here, or could my usage of DataTemplates be preventing the image from stretching properly?

Re: Setting the Stretch of an Image element contained in a DataTemplate in UserControl.Resources

Posted: 12 Mar 2020, 20:44
by sfernandez
Hi,

It could probably be a problem of the layout used by the templates and the list.

Could you try setting a fixed size to the images to see if at least images stretch inside that fixed size:
<Image Width="200" Height="200"
    Source="{Binding Path=MainBitmapSource}" 
    Stretch="{Binding Path=ImageStretch}"
    RenderTransform="{Binding Path=ImageTransformGroup}"
    SizeChanged="OnSizeChanged"/>

Re: Setting the Stretch of an Image element contained in a DataTemplate in UserControl.Resources

Posted: 12 Mar 2020, 21:43
by jpattersonCSpeed
Setting a width and height made the image stretch to those bounds. Would width and height values be necessary in this instance?

Re: Setting the Stretch of an Image element contained in a DataTemplate in UserControl.Resources

Posted: 12 Mar 2020, 21:59
by sfernandez
My initial doubt here was if Stretch binding was working or not. Having a fixed size in the image made that easier to test.

What is happening then is that having an Image inside a Grid cell of type * means that it will expand to fill that space, if the Grid does not have a fixed size, then it will also expand to fill parent's space, and so on... That makes no difference between Fill,Uniform or UniformToFill stretch values, only None has a meaning there (take the original Image space).

At some point you have to define some limits (relative using Grid star sizes, or absolute in pixels) in the layout so the Images fit in that available space.

Re: Setting the Stretch of an Image element contained in a DataTemplate in UserControl.Resources

Posted: 18 Mar 2020, 14:11
by jpattersonCSpeed
Alright thank you. I can supply a height for the image, which will allow it to size properly since the area for it in the application is more constrained by height.

Re: Setting the Stretch of an Image element contained in a DataTemplate in UserControl.Resources

Posted: 18 Mar 2020, 17:39
by sfernandez
Ok, I think we can mark this as solved then.