M
M
Mikhail Usotsky2019-04-03 13:45:14
WPF
Mikhail Usotsky, 2019-04-03 13:45:14

How to get the current dimensions of an element without its resize event?

I have a code like this taken from the internet.

public static class SizeObserver
{
    public static readonly DependencyProperty ObserveProperty = DependencyProperty.RegisterAttached(
        "Observe",
        typeof(bool),
        typeof(SizeObserver), new FrameworkPropertyMetadata(OnObserveChanged));
    
    public static readonly DependencyProperty ObservedWidthProperty = DependencyProperty.RegisterAttached(
        "ObservedWidth",
        typeof(double),
        typeof(SizeObserver));

    public static readonly DependencyProperty ObservedHeightProperty = DependencyProperty.RegisterAttached(
        "ObservedHeight",
        typeof(double),
        typeof(SizeObserver));

    public static bool GetObserve(FrameworkElement frameworkElement) => (bool)frameworkElement.GetValue(ObserveProperty);
    public static void SetObserve(FrameworkElement frameworkElement, bool observe) => frameworkElement.SetValue(ObserveProperty, observe);

    public static double GetObservedWidth(FrameworkElement frameworkElement) => (double)frameworkElement.GetValue(ObservedWidthProperty);
    public static void SetObservedWidth(FrameworkElement frameworkElement, double observedWidth) => frameworkElement.SetValue(ObservedWidthProperty, observedWidth);

    public static double GetObservedHeight(FrameworkElement frameworkElement) => (double)frameworkElement.GetValue(ObservedHeightProperty);
    public static void SetObservedHeight(FrameworkElement frameworkElement, double observedHeight) => frameworkElement.SetValue(ObservedHeightProperty, observedHeight);

    private static void OnObserveChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
    {
        var frameworkElement = (FrameworkElement)dependencyObject;

        if ((bool)e.NewValue)
        {
            frameworkElement.SizeChanged += OnFrameworkElementSizeChanged;
            UpdateObservedSizesForFrameworkElement(frameworkElement);
        }
        else
        {
            frameworkElement.SizeChanged -= OnFrameworkElementSizeChanged;
        }
    }

    private static void OnFrameworkElementSizeChanged(object sender, SizeChangedEventArgs e)
    {
        UpdateObservedSizesForFrameworkElement((FrameworkElement)sender);
    }

    private static void UpdateObservedSizesForFrameworkElement(FrameworkElement frameworkElement)
    {
        // WPF 4.0 onwards
        frameworkElement.SetCurrentValue(ObservedWidthProperty, frameworkElement.ActualWidth);
        frameworkElement.SetCurrentValue(ObservedHeightProperty, frameworkElement.ActualHeight);
    }
}

But the problem is that this class only works when there are some changes in the interface element. I can't use the methods because I have MVVM. And getting the ActualWidth and ActualHeight values ​​​​is very necessary. If one object is used for the interface, then the values ​​are immediately obtained. But here I have several such objects. Once launched, only one object can get information about the current size of the interface. But the rest of the objects are not up to date. When you switch to the next object, the element's current size data may be out of date. Until I resize the window. And this is very inconvenient.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
R
Roman, 2019-04-23
@WNeZRoS

If you do Observe through bindings, then everything works right away, without the SizeChanged event.

private static void OnObserveChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
    var frameworkElement = (FrameworkElement)dependencyObject;

    if ((bool)e.NewValue)
    {
        frameworkElement.SetBinding(ObservedWidthProperty, new Binding(nameof(FrameworkElement.ActualWidth)) { RelativeSource = RelativeSource.Self });
        frameworkElement.SetBinding(ObservedHeightProperty, new Binding(nameof(FrameworkElement.ActualHeight)) { RelativeSource = RelativeSource.Self });
    }
    else
    {
        frameworkElement.ClearValue(ObservedWidthProperty);
        frameworkElement.ClearValue(ObservedHeightProperty);
    }
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question