或者,您可以扩展 Image 并实现 MeasureOverride 和 ArrangeOverride 以更改图像 DPI 的效果:
class DpiAgnosticImage : Image
{
protected override Size MeasureOverride(Size constraint)
{
var bitmapImage = Source as BitmapImage;
var desiredSize = bitmapImage == null
? base.MeasureOverride(constraint)
: new Size(bitmapImage.PixelWidth, bitmapImage.PixelHeight);
var dpiScale = MiscUtil.GetDpiScale(this);
desiredSize = new Size(desiredSize.Width / dpiScale.Width, desiredSize.Height / dpiScale.Height);
desiredSize = ImageUtilities.ConstrainWithoutDistorting(desiredSize, constraint);
if (UseLayoutRounding)
{
desiredSize.Width = Math.Round(desiredSize.Width);
desiredSize.Height= Math.Round(desiredSize.Height);
}
return desiredSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
return new Size(Math.Round(DesiredSize.Width), Math.Round(DesiredSize.Height));
}
}
在 xaml 中使用它,就好像它是一个图像:
<Grid>
<local:DpiAgnosticImage
Stretch="None"
Source="{Binding ViewImage}">
<Image.RenderTransform>
<ScaleTransform
x:Name="SomeName"/>
</Image.RenderTransform>
</local:DpiAgnosticImage>
</Grid>
上述代码的缺陷(据我所知):
- 忽略拉伸
- 假设 Source 是 BitmapImage
=== 编辑 - Will 的评论表明他想知道 GetDpiScale() 中的内容
public static Size GetDpiScale(Visual visual)
{
var source = PresentationSource.FromVisual(visual);
var dpiScale = new Size(
source.CompositionTarget.TransformToDevice.M11,
source.CompositionTarget.TransformToDevice.M22);
return dpiScale;
}