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

How to bind to attached property in UWP?

我需要将控件的 属性 绑定到 XAML 中附加的 属性(以便附加的 属性 成为绑定的源),我不知道该怎么做——VS2015 给我“Value does not fall within the expected range”错误,当我 运行 应用程序时,我得到一个例外。

下面显示的技术在 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>

我没有在上面的 TextBlock 上显示 "Hello world!"(这是附加的 Foo 的默认值 属性),而是得到 XamlParseException,从初始化组件。和往常一样,异常对象不包含任何有用的信息。

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

那么正确的做法是什么?

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

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

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

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

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

我发现以下更改也有效:

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

[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" 
         />