tkawa
Topic Author
Posts: 1
Joined: 14 Sep 2018, 12:56

Pushing read-only GUI properties back into ViewModel

14 Sep 2018, 13:37

How do you write the following code as C++?

xaml file
<UserControl ...
    SizeObserver.Observe="True"
    SizeObserver.ObservedWidth="{Binding ActualWidth, Mode=OneWayToSource}"
    SizeObserver.ObservedHeight="{Binding ActualHeight, Mode=OneWayToSource}"
cs file
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)
    {
        frameworkElement.AssertNotNull("frameworkElement");
        return (bool)frameworkElement.GetValue(ObserveProperty);
    }

    public static void SetObserve(FrameworkElement frameworkElement, bool observe)
    {
        frameworkElement.AssertNotNull("frameworkElement");
        frameworkElement.SetValue(ObserveProperty, observe);
    }

    public static double GetObservedWidth(FrameworkElement frameworkElement)
    {
        frameworkElement.AssertNotNull("frameworkElement");
        return (double)frameworkElement.GetValue(ObservedWidthProperty);
    }

    public static void SetObservedWidth(FrameworkElement frameworkElement, double observedWidth)
    {
        frameworkElement.AssertNotNull("frameworkElement");
        frameworkElement.SetValue(ObservedWidthProperty, observedWidth);
    }

    public static double GetObservedHeight(FrameworkElement frameworkElement)
    {
        frameworkElement.AssertNotNull("frameworkElement");
        return (double)frameworkElement.GetValue(ObservedHeightProperty);
    }

    public static void SetObservedHeight(FrameworkElement frameworkElement, double observedHeight)
    {
        frameworkElement.AssertNotNull("frameworkElement");
        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)
    {
        frameworkElement.SetCurrentValue(ObservedWidthProperty, frameworkElement.ActualWidth);
        frameworkElement.SetCurrentValue(ObservedHeightProperty, frameworkElement.ActualHeight);
    }
}
 
User avatar
sfernandez
Site Admin
Posts: 1344
Joined: 22 Dec 2011, 19:20

Re: Pushing read-only GUI properties back into ViewModel

19 Sep 2018, 11:57

Hi, it would be like this:
struct SizeObserver
{
    static const DependencyProperty* ObserveProperty;
    static const DependencyProperty* ObservedWidthProperty;
    static const DependencyProperty* ObservedHeightProperty;

    static bool GetObserve(const FrameworkElement* frameworkElement)
    {
        AssertNotNull(frameworkElement);
        return frameworkElement->GetValue<bool>(ObserveProperty);
    }

    static void SetObserve(FrameworkElement* frameworkElement, bool observe)
    {
        AssertNotNull(frameworkElement);
        frameworkElement->SetValue<bool>(ObserveProperty, observe);
    }

    static float GetObservedWidth(const FrameworkElement* frameworkElement)
    {
        AssertNotNull(frameworkElement);
        return frameworkElement->GetValue<float>(ObservedWidthProperty);
    }

    static void SetObservedWidth(FrameworkElement* frameworkElement, float observedWidth)
    {
        AssertNotNull(frameworkElement);
        frameworkElement->SetValue<float>(ObservedWidthProperty, observedWidth);
    }

    static float GetObservedHeight(const FrameworkElement* frameworkElement)
    {
        AssertNotNull(frameworkElement);
        return frameworkElement->GetValue<float>(ObservedHeightProperty);
    }

    static void SetObservedHeight(FrameworkElement* frameworkElement, float observedHeight)
    {
        AssertNotNull(frameworkElement);
        frameworkElement->SetValue<float>(ObservedHeightProperty, observedHeight);
    }

private:
    static void OnObserveChanged(DependencyObject* dependencyObject, const DependencyPropertyChangedEventArgs& e)
    {
        FrameworkElement* frameworkElement = (FrameworkElement*)dependencyObject;

        if (*static_cast<const bool*>(e.newValue))
        {
            frameworkElement->SizeChanged() += &OnFrameworkElementSizeChanged;
            UpdateObservedSizesForFrameworkElement(frameworkElement);
        }
        else
        {
            frameworkElement->SizeChanged() -= &OnFrameworkElementSizeChanged;
        }
    }

    static void OnFrameworkElementSizeChanged(BaseComponent* sender, const SizeChangedEventArgs& e)
    {
        UpdateObservedSizesForFrameworkElement((FrameworkElement*)sender);
    }

    static void UpdateObservedSizesForFrameworkElement(FrameworkElement* frameworkElement)
    {
        frameworkElement->SetCurrentValue<float>(ObservedWidthProperty, frameworkElement->GetActualWidth());
        frameworkElement->SetCurrentValue<float>(ObservedHeightProperty, frameworkElement->GetActualHeight());
    }

    NS_IMPLEMENT_INLINE_REFLECTION(SizeObserver)
    {
        NsMeta<TypeId>("SizeObserver");

        Ptr<DependencyData> data = NsMeta<DependencyData>(TypeOf<SelfClass>());

        data->RegisterProperty<bool>(ObserveProperty, "Observe",
            FrameworkPropertyMetadata::Create(false, &OnObserveChanged));

        data->RegisterProperty<float>(ObservedWidthProperty, "ObservedWidth",
            FrameworkPropertyMetadata::Create(0.0f));

        data->RegisterProperty<float>(ObservedHeightProperty, "ObservedHeight",
            FrameworkPropertyMetadata::Create(0.0f));
    }
};

Who is online

Users browsing this forum: No registered users and 14 guests