Instead of setting the Window DataContext to the entire collection, what about setting it to the currently selected item? Then the image Source property can be binded to ImageFrame (like you have already redundantly done - you do it in code too) and the TextBlock Text property can be binded to Name like you have it. You can get rid of the DataContext binding on the TextBlock and the Image since you'd be using the inherited DataContext.
Note you're going to need to provide a property in your Photo class to bind to for the name...a private field isn't going to work.
Here's an example (I did this in Silverlight since you mention Silverlight in your tags...same things apply to WPF. Also note that I changed the URIs for my test code so I could use my images.)
public partial class ImageTestPage : UserControl
{
int currentIndex = 0;
ObservableCollection<Photo> photos = new ObservableCollection<Photo>();
public ImageTestPage()
{
InitializeComponent();
photos.Add(new Photo("Images/Airplane.png"));
photos.Add(new Photo("Images/Silverlight_Logo.jpg"));
this.DataContext = photos[currentIndex];
}
private void NextPhoto(object sender, RoutedEventArgs e)
{
currentIndex++;
if (currentIndex == photos.Count)
currentIndex = 0;
this.DataContext = photos[currentIndex];
}
}
public class Photo
{
BitmapImage _image;
public Photo(string path)
{
Name = path;
Uri source = new Uri(path, UriKind.Relative);
_image = new BitmapImage(source);
}
public string Name { get; set; }
public BitmapImage ImageFrame { get { return _image; } set { _image = value; } }
}
<Grid x:Name="LayoutRoot" Background="White">
<Button Name="nextButton" Content="Next" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10" Click="NextPhoto" />
<Image Grid.Column="0"
Grid.Row="0"
Stretch="Fill"
Source="{Binding ImageFrame}"
Margin="40" />
<TextBlock Text="{Binding Name}" Margin="10,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Bottom" />
</Grid>