Зачем?
В любой Windows 8/RT прилижении требуется отображать определенное количество графики. Ресурсы можно черпать повсеместно: напрямую из Web и постоянно выкачивать файлы; единажды получив файлы работать с ними через IsolatedStorage
и так далее. Все хорошо до таго момента, пока загрузка этой графики не начинает занимать продолжнительное время (даже секунда это много). В этот момент требуется визуально «обнадежить» пользователя, и занять пустое место, на котором через мгновение появится изображение. Тут нам на помощь приходит ProgressRing
и, естественно, удобнее всего написать один раз контрол и забыть об это надолго.
Идея
Идея действительнобанальна: Border
, Image
, ProgressRing
— больше ничего нам не понадобится.
Border
: на тот случай, если требуется обвести картинку. Далеко не самый обязательный элемент, но, иногда, очень необходимый.-
ProgressRing
: будет виден в тот момент, когдаImageSource
уже назначено, ноImage
еще не открыт. -
Image
: естественно, самый важный элемент ради которого мы все и затеяли.
Принцип работы
Просто играемся с прозрачностью ProgressRing
. Имеем две точки входа: событие ImageOpened
(скрываем ProgressRing
) и место назначения нового ImageSource
(показываемProgressRing
).
Код
ProgressImage.xaml
<UserControl
x:Class="test.Controls.ProgressImage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:test.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<Border x:Name="Border" BorderThickness="1" >
<Grid>
<ProgressRing x:Name="Ring" Width="100" Height="100" IsActive="True" Foreground="#FF6D31F5" />
<Image x:Name="Image" Margin="0" ImageOpened="Image_OnImageOpened" />
</Grid>
</Border>
</UserControl>
ProgressImage.cs
public sealed partial class ProgressImage : UserControl
{
#region Common
public ProgressImage()
{
InitializeComponent();
}
private void Image_OnImageOpened(object sender, RoutedEventArgs e)
{
Ring.Opacity = 0;
}
#endregion
#region Dependency
private static readonly Color DefRingColor = Colors.BlueViolet;
private static readonly Color DefBorderColor = Colors.White;
private static readonly ImageSource DefSource = null;
private const Stretch DefStretch = Stretch.None;
/// <summary>
/// Set Image Source
/// </summary>
public ImageSource Source
{
get { return (ImageSource)GetValue(SourceProperty); }
set { SetValue(SourceProperty, value); }
}
public static readonly DependencyProperty SourceProperty = DependencyProperty.Register("Source", typeof(ImageSource), typeof(ProgressImage), new PropertyMetadata(DefSource,SourceChanged));
private static void SourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var controll = (ProgressImage)d;
var val = (ImageSource)e.NewValue;
controll.Image.Source = val;
controll.Ring.Opacity = 100;
}
/// <summary>
/// Set ProgressRing Size
/// </summary>
public int ProgressRingSize
{
get { return (int)GetValue(ProgressRingSizeProperty); }
set { SetValue(ProgressRingSizeProperty, value); }
}
public static readonly DependencyProperty ProgressRingSizeProperty = DependencyProperty.Register("ProgressRingSize", typeof(int), typeof(ProgressImage),
new PropertyMetadata(55, ProgressRingSizeChanged));
private static void ProgressRingSizeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var controll = (ProgressImage)d;
var val = (int)e.NewValue;
controll.Ring.Width = val;
controll.Ring.Height = val;
}
/// <summary>
/// Set ProgressRing Color
/// </summary>
public Color ProgressRingColor
{
get { return (Color)GetValue(ProgressRingcolorProperty); }
set { SetValue(ProgressRingcolorProperty, value); }
}
public static readonly DependencyProperty ProgressRingcolorProperty = DependencyProperty.Register("ProgressRingColor", typeof(Color), typeof(ProgressImage),
new PropertyMetadata(DefRingColor, ProgressRingColorChanged));
private static void ProgressRingColorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var controll = (ProgressImage)d;
var val = (Color)e.NewValue;
controll.Ring.Foreground = new SolidColorBrush(val);
}
/// <summary>
/// Set Border Color
/// </summary>
public Color BorderColor
{
get { return (Color)GetValue(BorderColorProperty); }
set { SetValue(BorderColorProperty, value); }
}
public static readonly DependencyProperty BorderColorProperty = DependencyProperty.Register("BorderColor", typeof(Color), typeof(ProgressImage),
new PropertyMetadata(DefBorderColor, BorderColorChanged));
private static void BorderColorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var controll = (ProgressImage)d;
var val = (Color)e.NewValue;
controll.Border.BorderBrush = new SolidColorBrush(val);
}
/// <summary>
/// Set BorderThickness
/// </summary>
public double BorderSize
{
get { return (double)GetValue(BorderSizeProperty); }
set { SetValue(BorderSizeProperty, value); }
}
public static readonly DependencyProperty BorderSizeProperty = DependencyProperty.Register("BorderSize", typeof(double), typeof(ProgressImage), new PropertyMetadata(0.0, BorderSizeChanged));
private static void BorderSizeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var controll = (ProgressImage)d;
var val = (double)e.NewValue;
controll.Border.BorderThickness = new Thickness(val);
}
/// <summary>
/// Set Border Corner Radius
/// </summary>
public int BorderCornerRadius
{
get { return (int)GetValue(BorderCornerRadiusProperty); }
set { SetValue(BorderCornerRadiusProperty, value); }
}
public static readonly DependencyProperty BorderCornerRadiusProperty = DependencyProperty.Register("BorderCornerRadius", typeof(int), typeof(ProgressImage), new PropertyMetadata(0, BorderCornerRadiusChanged));
private static void BorderCornerRadiusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var controll = (ProgressImage)d;
var val = (int)e.NewValue;
controll.Border.CornerRadius = new CornerRadius(val);
}
/// <summary>
/// Set Image Stretch
/// </summary>
public Stretch ImageStretch
{
get { return (Stretch)GetValue(ImageStretchProperty); }
set { SetValue(ImageStretchProperty, value); }
}
public static readonly DependencyProperty ImageStretchProperty = DependencyProperty.Register("ImageStretch", typeof(Stretch), typeof(ProgressImage), new PropertyMetadata(DefStretch, ImageStretchChanged));
private static void ImageStretchChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var controll = (ProgressImage)d;
var val = (Stretch)e.NewValue;
controll.Image.Stretch = val;
}
/// <summary>
/// Set Image Stretch
/// </summary>
public double ImageMargin
{
get { return (double)GetValue(ImageMarginProperty); }
set { SetValue(ImageMarginProperty, value); }
}
public static readonly DependencyProperty ImageMarginProperty = DependencyProperty.Register("ImageMargin", typeof(double), typeof(ProgressImage), new PropertyMetadata(0.0, ImageMarginChanged));
private static void ImageMarginChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var controll = (ProgressImage)d;
var val = (double)e.NewValue;
controll.Image.Margin = new Thickness(val);
}
#endregion
}
Список насроек ключает в себя (имена говорящие, но все равно стоит пояснить):
Source
— назначениеImageSource
ProgressRingSize
— размерыProgressRing
ProgressRingColor
— цветProgressRing
BorderColor
— цветBorder
BorderSize
— размерBorderThickness
BorderCornerRadius
— размер радиуса угловBorder
ImageStretch
— говорит само за себяImageMargin
— назначениеMargin
дляImage
относительноBorder
ControlBackground
— назначение цвета фона всего контрола
Использывать крайне просто:
Не забывае про:
xmlns:controls="using:test.Controls"
И легко используем:
<controls:ProgressImage x:Name="ProgressImage" Grid.Column="1" Margin="0,0,20,0" Width="300" Height="300" BorderSize="3" BorderColor="White" ProgressRingColor="Red" ImageStretch="None" ProgressRingSize="60" HorizontalAlignment="Right" VerticalAlignment="Center"/>
Что мы получаем?
Наличие под рукой такого контрола — позволяет в любую минуту его подправить под свои конкретные нужны. Основные настройки уже включены, а добавить новые — двухминутное дело. Искренне надеюсь, что кому-нибудь сэкономил время. А вот как выглядет это.
Объективная/необъективная критика, а также предложения по улучшению бутут крайне хорошо восприняты.
Автор: jimpanzer