删除或设置XAML元素的绝对变换

问题描述 投票:-1回答:1

我需要始终将XAML对象按1:1比例缩放,或者至少将imagebrush内容缩放,即使它的父对象在视图框中并且内容在X方向上也要压缩。

示例:Viewbox包含Label和ImageBrush。我希望标签文本可以缩放,但是只有ImageBrush大小-缩小时,它只会显示内容的右上角。

对象的视图模型无法访问比例因子。我一直在寻找一种删除或重置viewbox转换的方法,但一直找不到。是否存在一个,或者我必须将当前比例因子从父级传播到最终视图模型?除非绝对必要,否则我不希望在这里混用表示逻辑。

wpf xaml mvvm scale viewbox
1个回答
0
投票

这里是您可以做的基本示例。首先扩展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的大小更改,但文本保持其大小。

这是基本的实现,可能无法在所有情况下都起作用。

© www.soinside.com 2019 - 2024. All rights reserved.