如何绑定到UWP中的附加属性?

时间:2016-01-10 02:09:49

标签: c# xaml visual-studio-2015 winrt-xaml uwp

我需要将控件的属性绑定到XAML中的附加属性(以便附加属性成为绑定的源),我无法弄清楚如何做到这一点 - VS2015给了我“< strong>值不在预期范围内“错误,当我运行应用程序时,我得到一个例外。

下面显示的技术在WPF中完美运行。

以下是演示此问题的示例应用程序。

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>

而不是显示“Hello world!” (在上面的TextBlock上,这是Foo附加属性的默认值),我从InitializeComponent抛出 XamlParseException 。像往常一样,异常对象不包含任何有用的信息。

有趣的是,如果我尝试绑定到任何标准(内置到框架中)附加属性(如(Grid.Row)),就不会发生这种情况,所以似乎XAML解析器不允许我使用自定义附属物业提供者,这很荒谬......

那么这样做的正确方法是什么?

1 个答案:

答案 0 :(得分:5)

尝试使用x:Bind声明而不是Binding声明。

<Grid>
    <TextBlock Text="{x:Bind Path=(local:AttachedPropertyTest.Foo) }"
               HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>

但是,使用x:Bind通过生成代码来支持后面代码中的绑定。

经过一些实验,在生成XamlTypeInfo.g.cs文件的工具的问题中似乎发生了什么,该文件是已声明的Xaml元素的编译查找,不幸的是InitTypeTables()中缺少AttachedPropertyTest注册方法。

关于XamlTypeInfo类生成的一个有趣的article描述了您的问题,提出了一些建议,包括使用自定义IXamlMetadataProvider

我发现以下更改也有效:

从静态更改AttachedPropertyTest类的声明,并添加Bindable属性,这将使生成XamlTypeInfo类的工具检测到它。

[Bindable]
public 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);
    }
}

然后修改xaml声明以包含RelativeSource

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