Удаление или установка абсолютного преобразования элемента XAML - PullRequest
0 голосов
/ 30 марта 2020

Мне нужно, чтобы объект XAML всегда масштабировался до 1: 1 или, по крайней мере, содержимое imagebru sh, даже если его родитель находится в окне просмотра, а содержимое сжато в направлении X.

Пример: Viewbox содержит Label & ImageBru sh. Я хотел бы, чтобы текст метки масштабировался, но только размер ImageBru sh - при уменьшении он будет отображать только верхний угол содержимого.

Модель представления для объекта не имеет доступа к масштаб. Я искал способ удалить или сбросить преобразование viewbox, но я не смог его найти. Есть ли один или мне нужно будет распространить текущий масштабный коэффициент от родителя до конечной модели представления? Я бы предпочел не смешивать там логи презентаций c, если в этом нет необходимости.

Вот текущий 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>

1 Ответ

1 голос
/ 01 апреля 2020

Вот базовый c пример того, что вы можете сделать. Сначала расширьте класс 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>

В этом примере Ellipse следует за изменением размера Viewbox как обычно, но текст сохраняет свой размер.

Это базовая c реализация и может работать не во всех случаях.

...