Note: This solution might not be work with a data-bound list; I haven't tried that. But it works if you can name each item added to your UI (which must be done programmatically). But if animation is more important to you than the data-bound-ness of the items, then this could work.
Assuming you have a fixed number of items to move around, you can almost (but not quite) do it with Visual States. Here is an example that shows you how you can do it trivially for a single Button
that moves randomly whenever you click it.
XAML
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.Resources>
<PowerEase Power="2" x:Key="PowerEase"/>
</Grid.Resources>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="VSG">
<VisualState x:Name="Default">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)"
Storyboard.TargetName="button" To="{Binding LeftOffset}"
Duration="0:0:0.5" EasingFunction="{StaticResource PowerEase}"/>
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Top)"
Storyboard.TargetName="button" To="{Binding TopOffset}"
Duration="0:0:0.5" EasingFunction="{StaticResource PowerEase}"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Other">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)"
Storyboard.TargetName="button" To="{Binding LeftOffset}"
Duration="0:0:0.5" EasingFunction="{StaticResource PowerEase}"/>
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Top)"
Storyboard.TargetName="button" To="{Binding TopOffset}"
Duration="0:0:0.5" EasingFunction="{StaticResource PowerEase}"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Canvas>
<Button x:Name="button" Content="Button" Height="100" Width="150" Click="button_Click"/>
</Canvas>
</Grid>
Code
public partial class VSM : PhoneApplicationPage, INotifyPropertyChanged
{
public VSM()
{
this.InitializeComponent();
DataContext = this;
random_ = new Random();
}
double left_;
double top_;
bool inOtherState_ = false;
Random random_;
public double LeftOffset { get { return left_; } }
public double TopOffset { get { return top_; } }
private void button_Click(object sender, RoutedEventArgs e)
{
left_ = random_.NextDouble() * (ActualWidth - 150);
top_ = random_.NextDouble() * (ActualHeight - 100);
RaisePropertyChanged();
if (inOtherState_)
VisualStateManager.GoToState(this, "Default", false);
else
VisualStateManager.GoToState(this, "Other", false);
inOtherState_ = !inOtherState_;
}
void RaisePropertyChanged()
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(""));
}
public event PropertyChangedEventHandler PropertyChanged;
}
You should be able to generalize this to multiple Buttons, and using whatever databinding technique you need. The trick is that you must flip-flop between two visual states, and you can only do that in code. And if you don't have a fixed number of elements, you can generate the Visual States in code as well (but again, not by data binding).