I have a collection of images i want to show with FlipView. On each image I want to draw multiple rectangles, but to do this I need the current dimensions for the image after it has been rendered. I have the coordinates for the rectangles in the same list as my images. I get the dimensions from the images via ImageOpened event, but the problem is the FlipView event loads three images at the same time causing the different rectangles all to be drawn on the first image. Any suggestions?
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
itemList = e.Parameter as List<TableData>;
foreach (var blobImage in itemList)
{
var request = (HttpWebRequest)WebRequest.Create($"http://localhost:58941/api/image?id={blobImage.ImageBlobName}");
request.Method = "GET";
request.ContentType = "application/json";
WebResponse response = await request.GetResponseAsync();
if (response != null)
{
string responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
var myDict = JsonConvert.DeserializeObject<BlobImage>(responseString);
var jj = new MyImage(blobImage.ImageDescription, myDict.Uri, blobImage.GpsLatitude, blobImage.GpsLongitude, blobImage.GpsAltitude, blobImage.DateTime, blobImage.ObjectsDetected);
MyImages.Add(jj);
}
}
MyFlipView.ItemsSource = MyImages;
}
private void Image_ImageOpened(object sender, RoutedEventArgs e)
{
Image currentImageDimensions = sender as Image;
currentWidth = currentImageDimensions.ActualWidth;
currentHeight = currentImageDimensions.ActualHeight;
foreach (var imageRectangle in itemList)
{
for (int i = 0; i < imageRectangle.ObjectsDetected.Count; i++)
{
rectangle = new Rectangle();
var xMinConvert = Convert.ToDouble(imageRectangle.ObjectsDetected[i].xMin);
var yMinConvert = Convert.ToDouble(imageRectangle.ObjectsDetected[i].yMin);
var xMaxConvert = Convert.ToDouble(imageRectangle.ObjectsDetected[i].xMax);
var yMaxConvert = Convert.ToDouble(imageRectangle.ObjectsDetected[i].yMax);
var xMin = xMinConvert * currentWidth;
var yMin = yMinConvert * currentHeight;
var xMax = xMaxConvert * currentWidth;
var yMax = yMaxConvert * currentHeight;
rectangle.Height = yMax - yMin;
rectangle.Width = xMax - xMin;
var left = ((bgWidth - currentWidth) / 2) + xMin;
var top = ((bgHeight - currentHeight) / 2) + yMin;
rectangle.Margin = new Thickness(left, top, 0, 0);
rectangle.Stroke = new SolidColorBrush(Windows.UI.Colors.Red);
rectangle.StrokeThickness = 1;
layoutRoot.Children.Add(rectangle);
}
}
}
Xaml:
<ScrollViewer DoubleTapped="scrollViewer_DoubleTapped" MinZoomFactor="1" ZoomMode="Enabled" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<Grid x:Name="cGrid" Width="{Binding ElementName=gridbg, Path=ActualWidth}" Height="{Binding ElementName=gridbg, Path=ActualHeight}">
<FlipView SelectionChanged="MyFlipView_SelectionChanged" Name="MyFlipView" Width="{Binding ElementName=gridbg, Path=ActualWidth}" Height="{Binding ElementName=gridbg, Path=ActualHeight}">
<FlipView.ItemTemplate>
<DataTemplate x:DataType="local:MyImage">
<Image Source="{Binding Image}" Stretch="Uniform" Height="{Binding ElementName=gridbg, Path=ActualHeight}" ImageOpened="Image_ImageOpened" />
</DataTemplate>
</FlipView.ItemTemplate>
</FlipView>
</Border>
<Canvas x:Name="layoutRoot">
</Canvas>
</Grid>
</ScrollViewer>
FlipViewcontrol supports virtualization at default, load three items at one time is as expected. If disabled the virtualization, all the items will be loaded into theFlipViewat one time.You have several ways to resolve your issue. Since you only need the
Rectangledrawing when oneFlipViewItemselected, you could put the drawing relative code snippet insideSelectionChangedevent handle ofFlipView. By doing this you may encounter the issue for getting theImageheight and width. Actually you should be able to know the image metadata by gettingStorageFileobject fromuriof the image. If you just want to get theImagecontrol for getting theHeightandWidth, you may useVisualTreeHelperto get theImagecontrol fromFlipView.Or you could consider to force load only one item to the
FlipVieweach time. For this you could useISupportIncrementalLoadingfor incremental loading.I'm not sure what you are drawing these rectangles for, consider to draw these rectangles to the image before you binding the images to the
FlipViewif possible.