如果我有一个多分辨率图标文件(.ico),我怎样才能确保WPF选择合适的图标?设置Image的宽度和高度是否会强制它,或者WPF是否只调整ico文件中的第一个图标?
这就是我目前正在使用的(它有效,但我想避免调整大小,如果这是正在发生的事情).
<MenuItem.Icon>
<Image Source="MyIcons.ico" Width="16" Height="16" />
</MenuItem.Icon>
Run Code Online (Sandbox Code Playgroud)
如果可能的话,我想在Xaml中声明这一点,而无需为其编写代码.
Nik*_*lay 29
我使用简单的标记扩展:
/// <summary>
/// Simple extension for icon, to let you choose icon with specific size.
/// Usage sample:
/// Image Stretch="None" Source="{common:Icon /Controls;component/icons/custom.ico, 16}"
/// Or:
/// Image Source="{common:Icon Source={Binding IconResource}, Size=16}"
/// </summary>
public class IconExtension : MarkupExtension
{
private string _source;
public string Source
{
get
{
return _source;
}
set
{
// Have to make full pack URI from short form, so System.Uri recognizes it.
_source = "pack://application:,,," + value;
}
}
public int Size { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
var decoder = BitmapDecoder.Create(new Uri(Source),
BitmapCreateOptions.DelayCreation,
BitmapCacheOption.OnDemand);
var result = decoder.Frames.SingleOrDefault(f => f.Width == Size);
if (result == default(BitmapFrame))
{
result = decoder.Frames.OrderBy(f => f.Width).First();
}
return result;
}
public IconExtension(string source, int size)
{
Source = source;
Size = size;
}
public IconExtension() { }
}
Run Code Online (Sandbox Code Playgroud)
Xaml用法:
<Image Stretch="None"
Source="{common:Icon Source={Binding IconResource},Size=16}"/>
Run Code Online (Sandbox Code Playgroud)
要么
<Image Stretch="None"
Source="{common:Icon /ControlsTester;component/icons/custom-reports.ico, 16}" />
Run Code Online (Sandbox Code Playgroud)
(基于 @Nikolay 很好的答案和关于绑定的后续评论)
您可能最好创建 aConverter而不是 a 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();
}
Run Code Online (Sandbox Code Playgroud)
然后,您必须像平常一样从 ResourceDictionary 中的转换器类创建资源:
<localConverters:IcoFileSizeSelectorConverter x:Key="IcoFileSizeSelector" />
Run Code Online (Sandbox Code Playgroud)
然后你可以使用Binding:
<Image Source="{Binding Path=IconResource, Converter={StaticResource IcoFileSizeSelector}, ConverterParameter=16}" />
Run Code Online (Sandbox Code Playgroud)
PS:在转换器代码中,我们接受所有参数输入,即使是缺失或无效的参数。如果您像我一样喜欢使用实时 XAML 编辑,那么这种行为会更方便。
| 归档时间: |
|
| 查看次数: |
13841 次 |
| 最近记录: |