(на основе @Nikolay отличный ответ и последующий комментарий о связывании)
Вам, вероятно, будет лучше создать Converter
вместо MarkupExtension
, чтобы вы могли использовать Binding
. Используя ту же логику, что и @ Nikolay
/// <summary>
/// Forces the selection of a given size from the ICO file/resource.
/// If the exact size does not exists, selects the closest smaller if possible otherwise closest higher resolution.
/// If no parameter is given, the smallest frame available will be selected
/// </summary>
public class IcoFileSizeSelectorConverter : IValueConverter
{
public virtual object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var size = string.IsNullOrWhiteSpace(parameter?.ToString()) ? 0 : System.Convert.ToInt32(parameter);
var uri = value?.ToString()?.Trim();
if (string.IsNullOrWhiteSpace(uri))
return null;
if (!uri.StartsWith("pack:"))
uri = $"pack://application:,,,{uri}";
var decoder = BitmapDecoder.Create(new Uri(uri),
BitmapCreateOptions.DelayCreation,
BitmapCacheOption.OnDemand);
var result = decoder.Frames.Where(f => f.Width <= size).OrderByDescending(f => f.Width).FirstOrDefault()
?? decoder.Frames.OrderBy(f => f.Width).FirstOrDefault();
return result;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
Затем вы должны создать ресурс из вашего класса конвертера где-нибудь в ResourceDictionary, как обычно:
<localConverters:IcoFileSizeSelectorConverter x:Key="IcoFileSizeSelector" />
И тогда вы можете использовать Binding
:
<Image Source="{Binding Path=IconResource, Converter={StaticResource IcoFileSizeSelector}, ConverterParameter=16}" />
PS: в коде преобразователя мы принимаем все входные данные для параметра, даже отсутствующие или недействительные. Такое поведение удобнее, если вы, как и я, любите играть с живым редактированием XAML.