I am creating a photo viewer application and I want to implement zooming for an image. I created a ScrollViewer and placed the image there. It all works out of the box. I can make a zoom gesture, and it zooms out. Now, the next thing I want to implement is to load a high-resolution version of the image when triggering zoom gestures and dynamically swap the bitmap in the Image control when it is loaded. I want this to happen unhindered so that the user can continue to gesture and continue to zoom in and see a more detailed image. What is the best approach for this? This is the code I have. The problem with my code is that when replacing Image.Source, my gesture is interrupted, and the photo reset corresponds to the original size.Changing the ScrollViewer ZoomFactor does not help, as it seems to get reset when the image is replaced. I have a DataModel with the Image property, which initially returns null, but starts loading the image from the "file" in low resolution mode and calls OnPropertyChanged ("Image") when the download is complete. Calling LoadFullImage () loads the full-resolution version and causes OnPropertyChanged ("Image") to terminate.Calling LoadFullImage () loads the full-resolution version and causes OnPropertyChanged ("Image") to terminate.Calling LoadFullImage () loads the full-resolution version and causes OnPropertyChanged ("Image") to terminate.
Here are excerpts from DataModel.cs:
public async Task LoadFullImage()
{
loadFullImageTask = UpdateImage(0);
await loadFullImageTask;
}
public ImageSource Image
{
get
{
if (fullImage != null)
{
return fullImage;
}
else if (image != null)
{
return image;
}
else
{
Task loadImageTask = UpdateImage(768);
return null;
}
}
}
public bool FullImageLoading
{
get { return (this.loadFullImageTask != null) && (!this.loadFullImageTask.IsCompleted); }
}
public bool FullImageLoaded
{
get { return this.fullImage != null; }
}
Here is my MainPage.xaml:
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<ScrollViewer x:Name="imageViewer" HorizontalAlignment="Stretch" HorizontalScrollBarVisibility="Visible" VerticalAlignment="Stretch" MinZoomFactor="1" ZoomMode="Enabled" ViewChanged="imageViewer_ViewChanged">
<Image x:Name="image" Margin="0,0,0,0" Stretch="Uniform" Source="{Binding Image}" />
</ScrollViewer>
</Grid>
Here is my MainPage.xaml.cs:
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
FileOpenPicker filePicker = new FileOpenPicker();
filePicker.SuggestedStartLocation = PickerLocationId.ComputerFolder;
filePicker.FileTypeFilter.Add(".jpg");
StorageFile file = await filePicker.PickSingleFileAsync();
data = new DataModel(file);
imageViewer.DataContext = data;
}
private async void imageViewer_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
ScrollViewer imageViewer = (ScrollViewer)sender;
if (imageViewer.ZoomFactor > 1)
{
if (!data.FullImageLoaded && (!data.FullImageLoading))
{
int oldHeight = ((BitmapImage)data.Image).PixelHeight;
int oldWidth = ((BitmapImage)data.Image).PixelWidth;
double oldHOffset = imageViewer.HorizontalOffset;
double oldVOffset = imageViewer.VerticalOffset;
await data.LoadFullImage();
int newHeight = ((BitmapImage)data.Image).PixelHeight;
int newWidth = ((BitmapImage)data.Image).PixelWidth;
float ratio = (float)oldHeight / (float)newHeight;
imageViewer.MaxZoomFactor = imageViewer.MaxZoomFactor * ratio;
imageViewer.MinZoomFactor = imageViewer.MinZoomFactor * ratio;
imageViewer.ZoomToFactor(imageViewer.ZoomFactor * ratio);
}
}
}
As I already mentioned, the problem with this code is that the gesture is interrupted and the new image does not change / scrolls to the correct position, the user interface is not seamless. Thanks for any suggestions on how to solve this problem.
source
share