Create a gist now

Instantly share code, notes, and snippets.

@KooKiz /AdaptiveImage.cs Secret
Created Jan 13, 2016

using System;
using Windows.Networking.Connectivity;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
namespace CustomControls
{
public class AdaptiveImage : ContentControl
{
public static readonly DependencyProperty SourceProperty = DependencyProperty.Register(
"Source",
typeof(AdaptiveImageSource),
typeof(AdaptiveImage),
new PropertyMetadata(null, OnSourceChanged));
public static readonly DependencyProperty ImageTemplateProperty = DependencyProperty.Register(
"ImageTemplate",
typeof(DataTemplate),
typeof(AdaptiveImage),
null);
public AdaptiveImage()
{
this.LayoutRoot = new Grid();
this.Content = this.LayoutRoot;
this.ProgressIndicator = new ProgressRing
{
Foreground = new SolidColorBrush { Color = Colors.White },
Width = 100,
Height = 100,
HorizontalAlignment = HorizontalAlignment.Stretch,
VerticalAlignment = VerticalAlignment.Stretch
};
}
public DataTemplate ImageTemplate
{
get { return this.GetValue(ImageTemplateProperty) as DataTemplate; }
set { this.SetValue(ImageTemplateProperty, value); }
}
public AdaptiveImageSource Source
{
get { return this.GetValue(SourceProperty) as AdaptiveImageSource; }
set { this.SetValue(SourceProperty, value); }
}
protected Grid LayoutRoot { get; }
private FrameworkElement LowResImage { get; set; }
private FrameworkElement HiResImage { get; set; }
private ProgressRing ProgressIndicator { get; set; }
private static void OnSourceChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
(sender as AdaptiveImage)?.StartLoading();
}
private static bool ShouldLoadHiResolutionPicture()
{
var connectionCost = NetworkInformation.GetInternetConnectionProfile()?.GetConnectionCost();
if (connectionCost == null)
{
return false;
}
switch (connectionCost.NetworkCostType)
{
case NetworkCostType.Unrestricted:
return true;
case NetworkCostType.Fixed:
case NetworkCostType.Variable:
return !connectionCost.ApproachingDataLimit && !connectionCost.OverDataLimit && !connectionCost.Roaming;
default:
return false;
}
}
private FrameworkElement CreateImage()
{
var customElement = this.ImageTemplate?.LoadContent() as FrameworkElement;
if (customElement != null)
{
return customElement;
}
var image = new Image();
image.SetBinding(Image.SourceProperty, new Binding());
return image;
}
private void StartLoading()
{
this.LayoutRoot.Children.Clear();
this.LowResImage = null;
this.HiResImage = null;
var source = this.Source;
if (source?.LowResSource == null)
{
return;
}
var lowResSource = new BitmapImage { UriSource = new Uri(source.LowResSource) };
this.LowResImage = this.CreateImage();
this.LowResImage.DataContext = lowResSource;
this.LayoutRoot.Children.Add(this.LowResImage);
if (source.HiResSource != null && ShouldLoadHiResolutionPicture())
{
this.ProgressIndicator.IsActive = true;
this.LayoutRoot.Children.Add(this.ProgressIndicator);
var hiResSource = new BitmapImage();
hiResSource.ImageOpened += this.ImageOpened;
hiResSource.ImageFailed += this.ImageFailed;
hiResSource.UriSource = new Uri(source.HiResSource);
this.HiResImage = this.CreateImage();
this.HiResImage.DataContext = hiResSource;
this.LayoutRoot.Children.Add(this.HiResImage);
this.HiResImage.Visibility = Visibility.Collapsed;
}
}
private void ImageFailed(object sender, ExceptionRoutedEventArgs e)
{
this.ProgressIndicator.IsActive = false;
}
private void ImageOpened(object sender, RoutedEventArgs e)
{
if (this.HiResImage != null)
{
this.LayoutRoot.Children.Remove(this.LowResImage);
this.HiResImage.Visibility = Visibility.Visible;
this.ProgressIndicator.IsActive = false;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment