WPF: Могу ли я получить размер UIElement ПОСЛЕ применения преобразования?

Можно ли в WPF/Silverlight получить вычисленное значение UIElement после применения преобразования?

(Судя по комментарию ниже):

У меня есть панель стека, и я применил к ней TranformGroup. В этой группе есть два преобразования перевода и одно преобразование масштабирования.

(предупреждение, псевдокод впереди)

groupTransform.children.add(new TranslateTransform());
groupTransform.children.add(new ScaleTransform());
groupTransform.children.add(new TranslateTransform());
containerToScale.RenderTransform = groupTransform;
...
// code that sets values to all the transforms

Очевидно, меня больше всего интересует масштабное преобразование.


person Matthew Bonig    schedule 23.07.2009    source источник
comment
Применение преобразования является слишком общим. Что именно вы делаете? Какие свойства, методы и т. д. обеспечивают это преобразование? Покажите нам код.   -  person Kevin Montrose    schedule 23.07.2009


Ответы (3)


Мэтью, как вы указали, ActualWidth и ActualHeight не меняются, если вы применяете преобразования. ActualWidth и ActualHeight представляют рассчитанную ширину/высоту после того, как система компоновки завершила расчет размера элемента управления (на основе таких значений, как Margin, HorizontalAlignment и т. д.).

Один из способов получить размер элемента управления с учетом всех примененных к нему преобразований масштаба — пройти вверх по визуальному дереву и применить все преобразования масштаба к ActualWidth и ActualHeight элемента управления:

public static Size GetActualSize(FrameworkElement control)
{
    Size startSize = new Size(control.ActualWidth, control.ActualHeight);

    // go up parent tree until reaching root
    var parent = LogicalTreeHelper.GetParent(control);
    while(parent != null && parent as FrameworkElement != null && parent.GetType() != typeof(Window))
    {
        // try to find a scale transform
        FrameworkElement fp = parent as FrameworkElement;
        ScaleTransform scale = FindScaleTransform(fp.RenderTransform);
        if(scale != null)
        {
            startSize.Width *= scale.ScaleX;
            startSize.Height *= scale.ScaleY;
        }
        parent = LogicalTreeHelper.GetParent(parent);
    }
    // return new size
    return startSize;
}

public static ScaleTransform FindScaleTransform(Transform hayStack)
{
    if(hayStack is ScaleTransform)
    {
        return (ScaleTransform) hayStack;
    }
    if(hayStack is TransformGroup)
    {
        TransformGroup group = hayStack as TransformGroup;
        foreach (var child in group.Children)
        {
            if(child is ScaleTransform)
            {
                return (ScaleTransform) child;
            }
        }
    }
    return null;
}

Имейте в виду, что это может быть неэффективно, если ваше визуальное дерево глубокое или вы выполняете это много раз. Однако на практике я никогда не сталкивался с какими-либо проблемами с этим.

person Julia Schwarz    schedule 31.08.2012

вы можете просто применить преобразование:

control.LayoutTransform.Transform(new Point(0,0))

person Rob Fonseca-Ensor    schedule 23.07.2009

Да, вы можете проверить ActualWidth и ActualHeight на любом FrameworkElement, чтобы понять это. Вам нужно будет проверить, виден ли он, если у вас есть элементы, которые скрываются.

Если вы хотите узнать после загрузки элемента управления, используйте событие Loaded.

person mattmanser    schedule 23.07.2009
comment
Я проверил, и StackPanel.ActualWidth и ActualHeight не меняются, когда я применяю к ним преобразование. знак равно - person Matthew Bonig; 24.07.2009