Shinigamae
Shinigamae

Reputation: 862

Manipulate Image controls in WPF

I'm learning WPF in free time using Flickr.NET API.

The first feature I want to perform is search images by name/description/tags. This leads me to play around with Images in WPF.

This is my setup:

- XAML

<Grid>
    <ItemsControl x:Name="PhotoList" HorizontalAlignment="Left" Height="639" Margin="10,10,0,0" VerticalAlignment="Top" Width="1060" Style="{DynamicResource ScrollableItemControlStyle}" >
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel Orientation="Horizontal" Height="639" Width="1060"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
            <DataTemplate DataType="{x:Type sys:String}">
                <Image Width="200" Source="{Binding Url}" Margin="0,0,5,5" MouseDown="OpenSelectedImage" MouseEnter="Image_MouseEnter" MouseLeave="Image_MouseLeave">
                </Image>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
    <Button x:Name="BackButton" Style="{DynamicResource ModernButtonStyle}" Content="Back" HorizontalAlignment="Left" Margin="710,654,0,0" VerticalAlignment="Top" Width="360" Height="56  " TabIndex="2" Background="#FF6600CC" IsDefault="True" Foreground="White" Click="BackButton_Click"/>
</Grid>  

- C#

public ObservableCollection<PhotoResult> images;
public ImageSearchResult(List<PhotoResult> imageList)
{
    InitializeComponent();
    if (imageList.Count > 0)
    {
        images = new ObservableCollection<PhotoResult>();
        foreach (var image in imageList)
        {
            images.Add(image);
        }
        PhotoList.ItemsSource = images;
    }
}

Could we achive:

  1. My WrapPanel doesn't scroll at all.
  2. When a mouse hover an Image control, I can have their size changed (with animation) to indicate selection. But it overlays other control, not rearrange position. Could we solve this one? I think ZIndex doesn't work as expected in this case.
  3. Also, can we change the image border at selection? I'm not able to do it at the moment.

Upvotes: 1

Views: 416

Answers (1)

SSchuette
SSchuette

Reputation: 619

If you want to have some "Selection-Behaviour" you should use some WPF Control implementing ItemsControl - your "ItemsControl" does not provide any selection.

If you use a "Listbox" (MSDN ListBox) you can set your ItemsPanel to whatever you want. E.g. you could use a "UniformGrid" where each item shares the same size. You could set the desired rows/columns.

    <ItemsPanelTemplate x:Key="ItemsPanelTemplate">
        <UniformGrid Rows="2"/>
    </ItemsPanelTemplate>

To achieve your resizing "MouseOver" or to set the Border in the selection case, you could define an "ItemContainerStyle" for the ListBox.

        <Style x:Key="ListBoxItemStyle" TargetType="{x:Type ListBoxItem}">
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
        <Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
        <Setter Property="Padding" Value="2,0,0,0"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListBoxItem}">
                    <Border x:Name="border" BorderBrush="Black" BorderThickness="0">
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal"/>
                                <VisualState x:Name="MouseOver">
                                    <Storyboard>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.LayoutTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" Storyboard.TargetName="image">
                                            <EasingDoubleKeyFrame KeyTime="0" Value="1.25"/>
                                        </DoubleAnimationUsingKeyFrames>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.LayoutTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" Storyboard.TargetName="image">
                                            <EasingDoubleKeyFrame KeyTime="0" Value="1.25"/>
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Disabled"/>
                            </VisualStateGroup>
                            <VisualStateGroup x:Name="SelectionStates">
                                <VisualState x:Name="Unselected"/>
                                <VisualState x:Name="Selected">
                                    <Storyboard>
                                        <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" Storyboard.TargetName="border">
                                            <EasingColorKeyFrame KeyTime="0" Value="#FFB61F1F"/>
                                        </ColorAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="SelectedUnfocused"/>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <Image x:Name="image" Height="100" Width="100">
                            <Image.LayoutTransform>
                                <TransformGroup>
                                    <ScaleTransform/>
                                    <SkewTransform/>
                                    <RotateTransform/>
                                    <TranslateTransform/>
                                </TransformGroup>
                            </Image.LayoutTransform>
                        </Image>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsSelected" Value="true">
                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
                        </Trigger>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsSelected" Value="true"/>
                                <Condition Property="Selector.IsSelectionActive" Value="false"/>
                            </MultiTrigger.Conditions>
                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}}"/>
                        </MultiTrigger>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

In summary you can now use your ListBox combining the ItemsPanel and ItemContainerStyle in this way:

<ListBox ItemsPanel="{DynamicResource ItemsPanelTemplate}" 
         ItemsSource="{Binding Collection}"
         ItemContainerStyle="{DynamicResource ListBoxItemStyle}" />

This is probably not the complete solution for all your questions, but it should provide a good starting point.

Upvotes: 4

Related Questions