Architecting...a slideshow
I know this sounds silly and I could use some out-of-the-box solution, but I really want to build my own simple image slideshow. I've been doing application development in Silverlight/WPF for some time, but for whatever reason I can't wrap my head around this.
- I have an observable collection of
SlideshowItem
- Each
SlideshowItem
hasSource
which indicates where the image for it is located - I show a translucent box for each
SlideshowItem
(horizontal list using a stackpanel) and when you click, you should transition to that slide
So here's my problem: If I have that list with a stackpanel template, and under the list is an image taking up the size of the canvas, I can bind the context of the image to the selected SlideshowItem
. That's all well and good. But when I click/change the selected ind开发者_开发百科ex of the list, I want to do a crossfade or slide between two images.
How should I represent this in Silverlight? Should I actually have a scroll panel or something with all the images and then change between them? Or is it sufficient to use a single image control? Can I do this with states, or do I need to explicitly run a storyboard? Any samples would be appreciated.
You can use the TransitioningContentControl from the Silverlight Toolkit, however if you want to roll your own you will need two content controls and swap out the "Active" one on SelectionChanged events. You also can fire your storyboards here.
ContentControl _active;
private void LB_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (_active == Content1)
{
_active = Content2;
Content2Active.Begin();
} else
{
_active = Content1;
Content1Active.Begin();
}
_active.Content = LB.SelectedItem;
}
And the Xaml looks something like this. I just use strings and text, but this approach should work reasonable well for images too:
<Grid x:Name="LayoutRoot" Background="White" MaxHeight="200">
<Grid.Resources>
<Storyboard x:Name="Content1Active">
<DoubleAnimation From="0" To="1" Storyboard.TargetName="Content1" Storyboard.TargetProperty="(UIElement.Opacity)" />
<DoubleAnimation To="0" Storyboard.TargetName="Content2" Storyboard.TargetProperty="(UIElement.Opacity)" />
</Storyboard>
<Storyboard x:Name="Content2Active">
<DoubleAnimation From="0" To="1" Storyboard.TargetName="Content2" Storyboard.TargetProperty="(UIElement.Opacity)" />
<DoubleAnimation To="0" Storyboard.TargetName="Content1" Storyboard.TargetProperty="(UIElement.Opacity)" />
</Storyboard>
</Grid.Resources>
<StackPanel>
<ListBox x:Name="LB" SelectionChanged="LB_SelectionChanged" xmlns:sys="clr-namespace:System;assembly=mscorlib">
<sys:String>Red</sys:String>
<sys:String>Green</sys:String>
<sys:String>Blue</sys:String>
</ListBox>
<Grid>
<ContentControl x:Name="Content1" FontSize="40" Foreground="{Binding Content, RelativeSource={RelativeSource Self}}">
</ContentControl>
<ContentControl x:Name="Content2" FontSize="40" Foreground="{Binding Content, RelativeSource={RelativeSource Self}}">
</ContentControl>
</Grid>
</StackPanel>
</Grid>
Definitely you don't need the entire Image collection displayed in a scrollviewer/stackpanel. You can implement this in many different ways. I can explain a simple idea of Using one Image : As you said , define a SelectedSlide property in your ViewModel and bind that to an Image control ( Preferably a ContentControl with Image as its part of the ContentTemplate, so that you can have descriptions and other items in the same). This solution can give you the opportunity to add some storyboards so that if you increase your SelectedIndex(Another VM property) fire a storyboard to do a 'Left Move' animation and if you decrease do a 'Right Move' animation makes user feels like slides are coming from one side and going the other way. You can do pretty good UX on that set of storyboards.
Update (Idea 2) : Yes if we need the notion of the previous one leaving the view when new one coming in, we can architect it by using two ContentControls wrapped inside a CustomControl ( lets call it as SlideShowControl). SlideShowControl will have its mechanism to properly set DataContext of the two ContentControl based on the selectedIndex position. I have successfully made this control in one of my projects, the logic here is to switch the ContentControls through a storyboard so that we can have many different effects by swapping the storyboard. Suppose you move from Index 1 to 2, ContentControlA will animate to left, and B will come in to the View, and based on your next click ControlA will go sit either left or right of the View, and comes with new DataContext of the selected View.
精彩评论