Skip to content

Instantly share code, notes, and snippets.

@darinkes
Last active April 8, 2019 09:23
Show Gist options
  • Save darinkes/e513c861e47375c0070e7ec38857e2f3 to your computer and use it in GitHub Desktop.
Save darinkes/e513c861e47375c0070e7ec38857e2f3 to your computer and use it in GitHub Desktop.
AvaloniaUI Image with Updateable Source
using Avalonia;
using Avalonia.Controls;
using Avalonia.Media;
using Avalonia.Media.Imaging;
using Avalonia.Platform;
using System;
namespace Test.Desktop
{
public class MyImage : Control
{
/// <summary>
/// Defines the <see cref="Source"/> property.
/// </summary>
public static readonly StyledProperty<string> SourceProperty =
AvaloniaProperty.Register<Image, string>(nameof(Source));
/// <summary>
/// Defines the <see cref="Stretch"/> property.
/// </summary>
public static readonly StyledProperty<Stretch> StretchProperty =
AvaloniaProperty.Register<Image, Stretch>(nameof(Stretch), Stretch.Uniform);
static MyImage()
{
AffectsRender<Image>(SourceProperty, StretchProperty);
AffectsMeasure<Image>(SourceProperty, StretchProperty);
}
private IBitmap bitmap;
public string Source
{
get { return GetValue(SourceProperty); }
set
{
SetValue(SourceProperty, value);
if (!string.IsNullOrEmpty(value))
{
var uri = value.StartsWith("/")
? new Uri(value, UriKind.Relative)
: new Uri(value, UriKind.RelativeOrAbsolute);
var assets = AvaloniaLocator.Current.GetService<IAssetLoader>();
bitmap = new Bitmap(assets.Open(uri));
}
else
{
bitmap = null;
}
}
}
/// <summary>
/// Gets or sets a value controlling how the image will be stretched.
/// </summary>
public Stretch Stretch
{
get { return (Stretch)GetValue(StretchProperty); }
set { SetValue(StretchProperty, value); }
}
/// <summary>
/// Renders the control.
/// </summary>
/// <param name="context">The drawing context.</param>
public override void Render(DrawingContext context)
{
var source = bitmap;
if (source != null)
{
Rect viewPort = new Rect(Bounds.Size);
Size sourceSize = new Size(source.PixelSize.Width, source.PixelSize.Height);
Vector scale = Stretch.CalculateScaling(Bounds.Size, sourceSize);
Size scaledSize = sourceSize * scale;
Rect destRect = viewPort
.CenterRect(new Rect(scaledSize))
.Intersect(viewPort);
Rect sourceRect = new Rect(sourceSize)
.CenterRect(new Rect(destRect.Size / scale));
var interpolationMode = RenderOptions.GetBitmapInterpolationMode(this);
context.DrawImage(source, 1, sourceRect, destRect, interpolationMode);
}
}
/// <summary>
/// Measures the control.
/// </summary>
/// <param name="availableSize">The available size.</param>
/// <returns>The desired size of the control.</returns>
protected override Size MeasureOverride(Size availableSize)
{
var source = bitmap;
if (source != null)
{
Size sourceSize = new Size(source.PixelSize.Width, source.PixelSize.Height);
if (double.IsInfinity(availableSize.Width) || double.IsInfinity(availableSize.Height))
{
return sourceSize;
}
else
{
return Stretch.CalculateSize(availableSize, sourceSize);
}
}
else
{
return new Size();
}
}
/// <inheritdoc/>
protected override Size ArrangeOverride(Size finalSize)
{
var source = bitmap;
if (source != null)
{
var sourceSize = new Size(source.PixelSize.Width, source.PixelSize.Height);
var result = Stretch.CalculateSize(finalSize, sourceSize);
return result;
}
else
{
return new Size();
}
}
}
}
<local:MyImage Source="resm:default.png" VerticalAlignment="Center" Margin="5" Width="24" Height="24">
<i:Interaction.Behaviors>
<ia:DataTriggerBehavior Binding="{Binding State}" ComparisonCondition="Equal" Value="STATE1">
<ia:ChangePropertyAction PropertyName="Source" Value="resm:state1.png"/>
</ia:DataTriggerBehavior>
<ia:DataTriggerBehavior Binding="{Binding State}" ComparisonCondition="Equal" Value="STATE2">
<ia:ChangePropertyAction PropertyName="Source" Value="resm:state2.png"/>
</ia:DataTriggerBehavior>
<ia:DataTriggerBehavior Binding="{Binding State}" ComparisonCondition="Equal" Value="STATE3">
<ia:ChangePropertyAction PropertyName="Source" Value="resm:state3.png"/>
</ia:DataTriggerBehavior>
</i:Interaction.Behaviors>
</local:MyImage>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment