locked
[UWP][XAML]How do I bind to an attached property in UWP XAML? RRS feed

  • Question

  • I need to bind a property of a control to an attached property in XAML (so that the attached property becomes a source of the binding), and I can't figure out how to do it -- VS2015 gives me "Value does not fall within the expected range" error, and when I run the app, I get an exception.

    The technique shown below worked perfectly in WPF.

    Here is the sample app demonstrating the problem.

    AttachedPropertyTest.cs:

    namespace App7
    {
        public static class AttachedPropertyTest
        {
            public static readonly DependencyProperty FooProperty = DependencyProperty.RegisterAttached(
                "Foo", typeof(string), typeof(AttachedPropertyTest), new PropertyMetadata("Hello world!"));
    
            public static void SetFoo(DependencyObject element, string value)
            {
                element.SetValue(FooProperty, value);
            }
    
            public static string GetFoo(DependencyObject element)
            {
                return (string) element.GetValue(FooProperty);
            }
        }
    }

    MainPage.xaml:

    <!-- Based on the default MainPage.xaml template from VS2015.
         The only thing added is the TextBlock inside the Grid. -->
    <Page x:Class="App7.MainPage"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:local="using:App7"
          xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
          mc:Ignorable="d">
        <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
            <TextBlock Text="{Binding Path=(local:AttachedPropertyTest.Foo), RelativeSource={RelativeSource Self}}"
                       HorizontalAlignment="Center" VerticalAlignment="Center"/>
        </Grid>
    </Page>

    Instead of displaying "Hello world!" (which is a default value of the Foo attached property) on the TextBlock above, I get XamlParseException, thrown from InitializeComponent. As usual, the exception object does not contain any useful information.

    Interestingly enough, this doesn't happen if I try to bind to any standard (built into the framework) attached property like (Grid.Row), so it seems that the XAML parser just doesn't let me use a custom attached property provider, which is ridiculous...

    So what is the correct way of doing this?


    • Edited by Krunal Parekh Monday, January 11, 2016 2:31 AM subject
    Sunday, January 10, 2016 1:49 PM

Answers

  • There are plenty scenarious where attached property is the source of binding, for example Validation.Errors and DesignerProperties.IsInDesignMode from WPF.

    One guy gave me the solution on stackoverflow.

    It's not about the value (the attached property above has a default value of "Hello world!"), it's about the WinRT XAML engine is not smart enough to recognize my type unless I mark it with [BindableAttribute], or use it in XAML explicitly as you showed above (not inside a binding).

    The lack of documentation is a serious problem when it comes to UWP. The MSDN simply says that this attribute "Specifies that a type defined in C++ (?) can be used for binding [...] all types defined in C# are bindable by default", which is obviously not true.

    • Edited by Yarik-Raider Sunday, January 10, 2016 11:17 PM formatting
    • Proposed as answer by Magnus (MM8)MVP Monday, January 11, 2016 5:30 PM
    • Marked as answer by Krunal Parekh Thursday, January 21, 2016 10:43 AM
    Sunday, January 10, 2016 10:42 PM

All replies

  • Appearantly this doesn't seem to work unless you set the value of the attached property:

    <TextBlock local:AttachedPropertyTest.Foo="..." Text="{Binding Path=(local:AttachedPropertyTest.Foo), RelativeSource={RelativeSource Mode=Self}}" 
                       HorizontalAlignment="Center" VerticalAlignment="Center"/>


    But why are you trying to bind the Text property to an attached property like this? You might as well bind to a "normal" dependency property or to a CLR property. An attached dependency property is usually set to some value: https://msdn.microsoft.com/en-us/library/windows/apps/mt185581.aspx

    Hope that helps.

    Please remember to close your threads by marking helpful posts as answer and then start a new thread if you have a new question. Please don't ask several questions in the same thread.

    Sunday, January 10, 2016 7:16 PM
  • There are plenty scenarious where attached property is the source of binding, for example Validation.Errors and DesignerProperties.IsInDesignMode from WPF.

    One guy gave me the solution on stackoverflow.

    It's not about the value (the attached property above has a default value of "Hello world!"), it's about the WinRT XAML engine is not smart enough to recognize my type unless I mark it with [BindableAttribute], or use it in XAML explicitly as you showed above (not inside a binding).

    The lack of documentation is a serious problem when it comes to UWP. The MSDN simply says that this attribute "Specifies that a type defined in C++ (?) can be used for binding [...] all types defined in C# are bindable by default", which is obviously not true.

    • Edited by Yarik-Raider Sunday, January 10, 2016 11:17 PM formatting
    • Proposed as answer by Magnus (MM8)MVP Monday, January 11, 2016 5:30 PM
    • Marked as answer by Krunal Parekh Thursday, January 21, 2016 10:43 AM
    Sunday, January 10, 2016 10:42 PM