(基于@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 编辑,这种行为会更方便。