我需要始终将XAML对象按1:1比例缩放,或者至少将imagebrush内容缩放,即使它的父对象在视图框中并且内容在X方向上也要压缩。
示例:Viewbox包含Label和ImageBrush。我希望标签文本可以缩放,但是只有ImageBrush大小-缩小时,它只会显示内容的右上角。
对象的视图模型无法访问比例因子。我一直在寻找一种删除或重置viewbox转换的方法,但一直找不到。是否存在一个,或者我必须将当前比例因子从父级传播到最终视图模型?除非绝对必要,否则我不希望在这里混用表示逻辑。
这里是您可以做的基本示例。首先扩展Viewbox类:
public class ViewboxEx : Viewbox
{
private FrameworkElement _child;
#region InvertScaleH
/// <summary>
/// InvertScaleH Read-Only Dependency Property
/// </summary>
private static readonly DependencyPropertyKey InvertScaleHPropertyKey
= DependencyProperty.RegisterReadOnly("InvertScaleH", typeof(double), typeof(ViewboxEx),
new FrameworkPropertyMetadata((double)1));
public static readonly DependencyProperty InvertScaleHProperty
= InvertScaleHPropertyKey.DependencyProperty;
/// <summary>
/// Gets the InvertScaleH property. This dependency property
/// indicates invert scale factor to compensate for horizontal scale fo the Viewbox.
/// </summary>
public double InvertScaleH
{
get { return (double)GetValue(InvertScaleHProperty); }
}
/// <summary>
/// Provides a secure method for setting the InvertScaleH property.
/// This dependency property indicates invert scale factor to compensate for horizontal scale fo the Viewbox.
/// </summary>
/// <param name="value">The new value for the property.</param>
protected void SetInvertScaleH(double value)
{
SetValue(InvertScaleHPropertyKey, value);
}
#endregion
#region InvertScaleV
/// <summary>
/// InvertScaleV Read-Only Dependency Property
/// </summary>
private static readonly DependencyPropertyKey InvertScaleVPropertyKey
= DependencyProperty.RegisterReadOnly("InvertScaleV", typeof(double), typeof(ViewboxEx),
new FrameworkPropertyMetadata((double)1));
public static readonly DependencyProperty InvertScaleVProperty
= InvertScaleVPropertyKey.DependencyProperty;
/// <summary>
/// Gets the InvertScaleV property. This dependency property
/// indicates invert scale factor to compensate for vertical scale fo the Viewbox.
/// </summary>
public double InvertScaleV
{
get { return (double)GetValue(InvertScaleVProperty); }
}
/// <summary>
/// Provides a secure method for setting the InvertScaleV property.
/// This dependency property indicates invert scale factor to compensate for vertical scale fo the Viewbox.
/// </summary>
/// <param name="value">The new value for the property.</param>
protected void SetInvertScaleV(double value)
{
SetValue(InvertScaleVPropertyKey, value);
}
#endregion
public ViewboxEx()
{
Loaded += OnLoaded;
SizeChanged += (_,__) => UpdateScale();
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
UpdateChild();
}
protected override void OnVisualChildrenChanged(DependencyObject visualAdded, DependencyObject visualRemoved)
{
base.OnVisualChildrenChanged(visualAdded, visualRemoved);
UpdateChild();
}
private void UpdateChild()
{
if (_child != null)
{
_child.SizeChanged -= OnChild_SizeChanged;
}
_child = Child as FrameworkElement;
if (_child != null)
{
_child.SizeChanged += OnChild_SizeChanged;
}
UpdateScale();
}
private void OnChild_SizeChanged(object sender, SizeChangedEventArgs e)
{
UpdateScale();
}
private void UpdateScale()
{
if (_child == null)
return;
SetInvertScaleH(_child.ActualWidth / ActualWidth);
SetInvertScaleV(_child.ActualHeight / ActualHeight);
}
}
基本上,它是侦听Viewbox大小及其内容的变化,然后计算反比例因子。现在使用此比例因子:
<Window x:Class="YourNamespace.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:YourNamespace"
Title="MainWindow" Height="450" Width="800">
<Grid>
<local:ViewboxEx>
<Grid Width="100" Height="100">
<Ellipse Fill="Green"/>
<TextBlock Text="123" Margin="10,10,0,0">
<TextBlock.RenderTransform>
<ScaleTransform
ScaleX="{Binding InvertScaleH, RelativeSource={RelativeSource AncestorType={x:Type local:ViewboxEx}}}"
ScaleY="{Binding InvertScaleV, RelativeSource={RelativeSource AncestorType={x:Type local:ViewboxEx}}}"/>
</TextBlock.RenderTransform>
</TextBlock>
</Grid>
</local:ViewboxEx>
</Grid>
</Window>
在此示例中,椭圆像往常一样遵循Viewbox的大小更改,但文本保持其大小。
这是基本的实现,可能无法在所有情况下都起作用。