到目前为止,如果我想在我的XAML中创建一个带图像的按钮,我可以这样做:
<Button>
<Button.Content>
<Grid>
<Image Source="myimage.png" Width="45" RenderOptions.EdgeMode="Aliased" RenderOptions.BitmapScalingMode="High Quality"/>
</Grid>
</Button.Content>
<Button>
这很好用。现在我正在尝试使用RibbonButtons和RibbonApplicationMenuItems,事情似乎并没有很快发生。
RibbonButton有一个LargeImageSource和一个SmallImageSource ...如果我尝试像上面所示修改内容,则不会出现任何图像。如果我对大型和小型图像源使用48x48图像,则小图像最终会像素化。什么?我以为我可以指定别名和高质量,应用程序应该为我清洁地缩放图像。为什么不这样呢?
与RibbonApplicationMenuItem类似的问题。这个允许我指定一个ImageSource。如果我选择一个大的PNG,它看起来还可以,但是像素化(在资源管理器窗口中调整大小相同的PNG看起来很好),就像它被不适当地拉伸得更小。如果我使用嵌入了16x16,24x24,32x32,48x48等的ICO,它看起来像ICO中使用的最小图标并且拉伸得更大。
如果我使用应用程序图标正在使用的相同ICO文件(在应用程序顶部看起来很好,那么选择正确的嵌入图标),即使使用此ICO,RibbonApplicationMenuItem看起来也很差。
显然我在这里缺少一些关键的东西。我需要做什么才能使我的功能区导航中的按钮和项目看起来干净利落?
更多示例代码:
<RibbonApplicationMenuItem Header="Command Text" ImageSource="myimage.png" Command="{Binding MyCommand}" />
<RibbonButton LargeImageSource="myimage.png" Label="Command Text" KeyTip="C" Command="{Binding MyCommand}" />
编辑9/24/15:根据Adeeb Arangodan的要求,我正在添加更多代码并包括一些图片。
使用的一些原始图像的图片(ICO和各种尺寸的PNG):
此外,这里是更多示例代码。包括整个窗口和多个按钮尝试。如您所见,只有已正确调整大小的图像“paste_32.png”看起来很漂亮。每个其他按钮,无论是使用大于目标尺寸的ICO还是PNG,都会模糊不清。
<Window x:Class="RibbonDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
xmlns:r="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary">
<Grid>
<r:Ribbon>
<r:Ribbon.HelpPaneContent>
<r:RibbonButton SmallImageSource="pack://application:,,,/RibbonDemo;component/Images/help.ico" />
</r:Ribbon.HelpPaneContent>
<r:Ribbon.ApplicationMenu>
<r:RibbonApplicationMenu >
<r:RibbonApplicationMenuItem Header="Error" ImageSource="pack://application:,,,/RibbonDemo;component/Images/error.ico" />
<r:RibbonApplicationMenuItem Header="Print" ImageSource="pack://application:,,,/RibbonDemo;component/Images/print.ico" />
<r:RibbonApplicationMenuItem Header="Vendor" ImageSource="pack://application:,,,/RibbonDemo;component/Images/batch_logo.png" RenderOptions.EdgeMode="Aliased" RenderOptions.BitmapScalingMode="HighQuality" />
<r:RibbonApplicationMenuItem Header="Paste" ImageSource="pack://application:,,,/RibbonDemo;component/Images/paste_32.png" />
</r:RibbonApplicationMenu>
</r:Ribbon.ApplicationMenu>
<r:RibbonTab Header="Home">
<r:RibbonGroup Header="Home">
<r:RibbonMenuButton
LargeImageSource="pack://application:,,,/RibbonDemo;component/Images/error.ico"
SmallImageSource="pack://application:,,,/RibbonDemo;component/Images/error.ico" Label="Error">
</r:RibbonMenuButton>
<r:RibbonButton LargeImageSource="pack://application:,,,/RibbonDemo;component/Images/print.ico" Label="Help"/>
<r:RibbonButton LargeImageSource="pack://application:,,,/RibbonDemo;component/Images/batch_logo.png" Label="Vendor" RenderOptions.EdgeMode="Aliased" RenderOptions.BitmapScalingMode="HighQuality"/>
<r:RibbonButton LargeImageSource="pack://application:,,,/RibbonDemo;component/Images/paste_32.png" Label="Paste"/>
</r:RibbonGroup>
</r:RibbonTab>
</r:Ribbon>
</Grid>
</Window>
这就是我这样做的方式:
<RibbonButton Margin="3" LargeImageSource="/Resources/images/Home.png"
Label="Home" ToolTip="Show company detials" Command="{Binding ShowHomeCommand}">
我不确定这是最好的方法(并且如果某人有一个易于在XAML中使用的方法,则会将另一个解决方案标记为正确答案),但这对我来说在使用只有一种类型的ICO时是有效的图像,但不同的大小。我根据Nikolay的回答here创建了一个转换器。
[ValueConversion(typeof(string), typeof(ImageSource))]
public class IconExtractor32 : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string path = parameter.ToString();
var decoder = BitmapDecoder.Create(new Uri(path.ToString()), BitmapCreateOptions.DelayCreation, BitmapCacheOption.OnDemand);
// It is assumed that if multiple icons of the same size are available,
// that the first ones encountered are those intended for use.
var result = decoder.Frames.First(f => f.Width == 32);
if (result == default(BitmapFrame))
result = decoder.Frames.OrderBy(f => f.Width).First();
return result;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
我为每个标准尺寸(16,24,32等)创建了其中一个转换器,每个转换器可以单独使用。他们只需要传递一个ICO文件的路径。
然后我创建了一个父转换器,可以以“path,size”的形式传递一个字符串,这样在Button的XAML图像中可以使用相同的转换器。
[ValueConversion(typeof(string), typeof(ImageSource))]
public class IconExtractor : IValueConverter
{
private IconExtractor32 extractor32 = new IconExtractor32();
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string source = parameter.ToString();
string[] values = source.Split(',').Select(sValue => sValue.Trim()).ToArray();
if (2 != values.Count())
{
throw new NotImplementedException();
}
else
{
string path = "pack://application:,,," + values[0];
switch (values[1])
{
case "32":
return extractor32.Convert(value, targetType, path, culture);
default:
throw new NotImplementedException();
}
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
我不认为这是优雅的,我不确定它是否有效,它还没有(还)处理PNG或其他图像格式,对于ICO它只能处理一个图像(而不是多个)通过选择第一项来获得各种尺寸的不同图像。但它确实允许:
<Fluent:MenuItem.Icon>
<Binding Converter="{StaticResource iconExtractor}" ConverterParameter="/myapplication;component/Images/error.ico, 32"/>
</Fluent:MenuItem.Icon>