Use x:Bind with attached property (showing flyout)

438 Views Asked by At

I made "MVVM flyout" based on this post: https://marcominerva.wordpress.com/2015/01/15/how-to-open-and-close-flyouts-in-universal-apps-using-mvvm/

It is working well. But it is not working with compiled binding(x:Bind)

This:

 <Flyout local:FlyoutHelpers.Parent="{x:Bind ShowButton}"...

insead of this:

<Flyout local:FlyoutHelpers.Parent="{Binding ElementName=ShowButton}"...

throws strange error while building:

Error CS1503 Argument 1: cannot convert from 'Windows.UI.Xaml.Controls.Flyout' to 'Windows.UI.Xaml.FrameworkElement'

Is there any option how to use x:Bind?

1

There are 1 best solutions below

1
ZORRO On

The problem here is related to the generated code for {x:Bind}

As we know {x:Bind} uses generated code to achieve its benefits. And these codes can be found in obj folder, with names like (for C#) <view name>.g.cs. For more info, please see {x:Bind} markup exstrong texttension.

If you go to .g.cs file (I used FlyoutHelper in MainPage,so in my side, it's MainPage.g.cs), you will find the error is in Set_FlyoutDemoSample_FlyoutHelper_Parent method. This method is generated at compile time, FlyoutDemoSample is the namespace of my project. Its name may be different in your side.   enter image description here

If we go to the definition of this method, we will find the type of the first parameter in this method is FrameworkElement

public static void Set_FlyoutDemoSample_FlyoutHelper_Parent(global::Windows.UI.Xaml.FrameworkElement obj, global::Windows.UI.Xaml.FrameworkElement value, string targetNullValue)
{
    if (value == null && targetNullValue != null)
    {
        value = (global::Windows.UI.Xaml.FrameworkElement) global::Windows.UI.Xaml.Markup.XamlBindingHelper.ConvertValue(typeof(global::Windows.UI.Xaml.FrameworkElement), targetNullValue);
    }
    global::FlyoutDemoSample.FlyoutHelper.SetParent(obj, value);
}

However when using FlyoutHelper, the parameter we set here is a Flyout.   enter image description here Flyout class is not derived from FrameworkElement. So it throws an error: cannot convert from 'Windows.UI.Xaml.Controls.Flyout' to 'Windows.UI.Xaml.FrameworkElement'. If we change the first parameter's type to DependencyObject, all the codes will work well.

public static void Set_FlyoutDemoSample_FlyoutHelper_Parent(global::Windows.UI.Xaml.DependencyObject obj, global::Windows.UI.Xaml.FrameworkElement value, string targetNullValue)
{
    if (value == null && targetNullValue != null)
    {
        value = (global::Windows.UI.Xaml.FrameworkElement) global::Windows.UI.Xaml.Markup.XamlBindingHelper.ConvertValue(typeof(global::Windows.UI.Xaml.FrameworkElement), targetNullValue);
    }
    global::FlyoutDemoSample.FlyoutHelper.SetParent(obj, value);
}

However, these codes are generated automatically, if we rebuild this project, we will still get the same error. I'm not sure if this is a potential bug in UWP, but I think there is nothing we can do to fix it. So I'd suggest you still use Binding in this special scenario.