views:

14

answers:

1

I have a wrap panel full of rectangles, when you mouse over a rectangle it grows in size (using a storyboard animation) to simulate being magnified.

That all works fine, the problem is that if you mouse over the last rectangle in a row the magnification causes it to jump to the next line (because it grew too big to fit on the current line). I'm sure there is an elegant solution to prevent this scenario but I just can't figure it out. Any help would be greatly appreciated.

Here's the XAML that runs it all:

<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
    <ListBox Name="lstBox"
             Width="200"
             ScrollViewer.HorizontalScrollBarVisibility="Disabled"
             ScrollViewer.VerticalScrollBarVisibility="Disabled">
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel></WrapPanel>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>

        <ListBox.Resources>
            <Style TargetType="{x:Type ListBoxItem}">
                <Setter Property="HorizontalAlignment" Value="Center" />
                <Setter Property="FontSize" Value="12" />
                <Setter Property="LayoutTransform">
                    <Setter.Value>
                        <ScaleTransform
                    ScaleY="{Binding RelativeSource={RelativeSource self},
                                     Path=ScaleX}" />
                    </Setter.Value>
                </Setter>
                <Style.Triggers>
                    <EventTrigger RoutedEvent="Button.MouseEnter">
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation 
                            Storyboard.TargetProperty="LayoutTransform.ScaleX"
                            To="2" Duration="0:0:0.25" />
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                    <EventTrigger RoutedEvent="Button.MouseLeave">
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation 
                            Storyboard.TargetProperty="LayoutTransform.ScaleX"
                            To="1" Duration="0:0:.5" />
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                </Style.Triggers>
            </Style>
        </ListBox.Resources>

        <ListBoxItem>
            <Rectangle Fill="Red" Width="30" Height="20"></Rectangle>
        </ListBoxItem>
        <ListBoxItem>
            <Rectangle Fill="Red" Width="30" Height="20"></Rectangle>
        </ListBoxItem>
        <ListBoxItem>
            <Rectangle Fill="Red" Width="30" Height="20"></Rectangle>
        </ListBoxItem>
        <ListBoxItem>
            <Rectangle Fill="Red" Width="30" Height="20"></Rectangle>
        </ListBoxItem>
        <ListBoxItem>
            <Rectangle Fill="Red" Width="30" Height="20"></Rectangle>
        </ListBoxItem>
        <ListBoxItem>
            <Rectangle Fill="Red" Width="30" Height="20"></Rectangle>
        </ListBoxItem>
        <ListBoxItem>
            <Rectangle Fill="Red" Width="30" Height="20"></Rectangle>
        </ListBoxItem>
        <ListBoxItem>
            <Rectangle Fill="Red" Width="30" Height="20"></Rectangle>
        </ListBoxItem>
        <ListBoxItem>
            <Rectangle Fill="Red" Width="30" Height="20"></Rectangle>
        </ListBoxItem>
    </ListBox>
</Grid>

A: 

You can use RenderTransform instead of LayoutTransform, for example:

<Style TargetType="{x:Type ListBoxItem}"> 
  <Setter Property="RenderTransformOrigin" Value="0.5 0.5" />
  <Setter Property="RenderTransform"> 
    <Setter.Value> 
       <ScaleTransform
         ScaleY="{Binding ScaleX, RelativeSource={RelativeSource self}}" />
    </Setter.Value> 
  </Setter> 
  <Style.Triggers> 
    <EventTrigger RoutedEvent="Button.MouseEnter"> 
      <BeginStoryboard> 
        <Storyboard> 
          <DoubleAnimation
            Storyboard.TargetProperty="RenderTransform.ScaleX"
            To="2" Duration="0:0:0.25" /> 
        </Storyboard> 
      </BeginStoryboard> 
    </EventTrigger> 
    <EventTrigger RoutedEvent="Button.MouseLeave"> 
      <BeginStoryboard> 
        <Storyboard> 
          <DoubleAnimation  
            Storyboard.TargetProperty="RenderTransform.ScaleX" 
            To="1" Duration="0:0:.5" /> 
        </Storyboard> 
      </BeginStoryboard> 
    </EventTrigger> 
  </Style.Triggers> 
</Style> 

Note that this will not push neighboring items aside. If you want to push the neighboring items aside in a WrapPanel without affecting the wrapping, you'll need to have non-hovered items shrink while the hovered item grows. Computing animations in code to do this is not particularly difficult but is quite a bit more code than a couple of storyboards.

Ray Burns