【问题标题】:How to bind to attached property in UWP?如何绑定到 UWP 中的附加属性?
【发布时间】:2016-04-14 13:33:28
【问题描述】:

我需要将控件的属性绑定到 XAML 中的附加属性(以便附加属性成为绑定的源),但我不知道该怎么做——VS2015 给了我“值不在预期范围内”错误,并且在我运行应用程序时出现异常。

下面显示的技术在 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!” (这是 Foo 附加属性的默认值)在上面的 TextBlock 上,我得到了从 InitializeComponent 抛出的 XamlParseException。像往常一样,异常对象不包含任何有用的信息。

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

那么正确的做法是什么?

【问题讨论】:

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


    【解决方案1】:

    尝试使用 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" 
             />
    

    【讨论】:

    • x:Bind 在我设置Mode=OneWay 后无法立即编译。一次性绑定不是我需要的...
    • 不知道您需要使用 Mode=OneWay。更新了答案,使其更全面,并允许使用其他模式。
    • 1. Mode=OneWayBindings 的默认模式(与您提到的x:Bind 相比,默认情况下有Mode=OneTime)。 2. ReferenceSource 是什么意思?
    • 3. [Bindable] 属性完全解决了我的问题! 即使 VS 仍在大喊“值不在预期范围内”。似乎 WinRT XAML 引擎不够聪明,无法推断我正在使用该类型,因为它只是一个绑定源,而不是一个目标。当涉及到 UWP 时,缺乏文档是一个真正的问题(MSDN 只是说这个属性“指定在 C++ 中定义的类型可用于绑定 [...] 在 C# 中定义的所有类型默认情况下都是可绑定的”,呃……)。
    • Opps,我的意思是 RelativeSource,我必须更新它,是的,“值不在预期范围内”似乎是在这种情况下可以忽略的警告/错误。
    猜你喜欢
    • 2017-01-25
    • 1970-01-01
    • 2021-12-01
    • 2011-02-07
    • 2017-03-23
    • 1970-01-01
    • 2017-11-08
    • 1970-01-01
    • 2011-07-03
    相关资源
    最近更新 更多