【问题标题】:Removing or setting an absolute transform of XAML Element删除或设置 XAML 元素的绝对变换
【发布时间】:2020-03-30 12:53:15
【问题描述】:

我需要始终按 1:1 缩放 XAML 对象,或者至少缩放图像刷内容,即使它的父对象位于视图框中并且内容在 X 方向上被压缩。

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

对象的视图模型无权访问比例因子。我一直在寻找一种方法来删除或重置视图框变换,但我一直找不到。是否有或者我必须将当前的比例因子从父视图模型传播到最终视图模型?除非绝对必须,否则我宁愿不在那里混合表示逻辑。

这是我目前获得的当前 XAML:

           <ImageBrush ImageSource="{Binding Paint, Mode=OneWay, Converter={StaticResource BitmapToImageSourceConverter}}">
                <ImageBrush.RelativeTransform>
                    <MatrixTransform>
                        <MatrixTransform.Matrix>
                            <MultiBinding Converter="{StaticResource TimelineMatrixConverter}">
                                <Binding />
                                <Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type MatrixTransform}}" Path="Matrix" />
                            </MultiBinding>
                        </MatrixTransform.Matrix>
                    </MatrixTransform>
                </ImageBrush.RelativeTransform>
            </ImageBrush>

【问题讨论】:

  • 您可以使用 Root.ActualWidth/ViewBox.ActualWidth 对您的对象应用反向缩放变换,并在垂直缩放上相同。 (Root 是放置在 Viewbox 中的根对象。)
  • @Dmitry,不幸的是无法让它工作。现在我正在考虑在图像刷内容上反转实际的变换矩阵。
  • 你能发布一些你的 xaml 吗?
  • 您的 ImageBrush 不能被“包含”,它不是 UIElement。它是 ViewBox 的背景吗?或者你有一个用这个 ImageBrush 填充的矩形?
  • 啊,真的。这是一个网格背景,但没有单元格。

标签: wpf xaml mvvm scale viewbox


【解决方案1】:

这是您可以执行的基本示例。首先扩展 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的大小及其内容的变化,然后计算出invert scale factor。现在使用这个比例因子:

<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>

在此示例中,Ellipse 像往常一样跟随 Viewbox 的大小变化,但文本保持其大小。

这是一个基本的实现,可能并不适用于所有情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-04
    • 1970-01-01
    • 2012-11-28
    相关资源
    最近更新 更多