2016-01-10 4 views
2

Мне нужно привязать свойство элемента управления к прикрепленному свойству в XAML (так что присоединенное свойство станет источником привязки), и я не могу понять, как это сделать - VS2015 дает мне «Значение не попадает в ожидаемый диапазон "Ошибка, и когда я запускаю приложение, я получаю исключение.Как связать прикрепленное свойство в UWP?

Техника, показанная ниже, отлично работает в 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 выше, я получаю XamlParseException, выброшенный из InitializeComponent. Как обычно, объект исключения не содержит никакой полезной информации.

Интересно, что этого не происходит, если я пытаюсь связать с каким-либо стандартным (встроенным в фреймворк) прикрепленным свойством, например (Grid.Row), поэтому кажется, что синтаксический анализатор XAML просто не позволяет мне использовать пользовательский подключенный поставщик свойств , что смешно ...

Итак, каков правильный способ сделать это?

ответ

4

Попробуйте использовать объявление x: Bind вместо объявления привязки.

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

Однако, используя x: Bind работает, создавая код для поддержки привязки в коде позади.

После некоторого эксперимента, что, похоже, происходит в проблеме с инструментом, сгенерированным файлом XamlTypeInfo.g.cs, который является скомпилированным просмотром объявленных элементов Xaml, и, к сожалению, регистрация AttachedPropertyTest отсутствует в InitTypeTables ().

Интересного article по генерации класса XamlTypeInfo описывают ваш вопрос делает несколько предложений, в том числе с использованием пользовательского IXamlMetadataProvider

Я нашел следующие изменения также будут работать:

Измените объявление класса AttachedPropertyTest от static и добавьте атрибут 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" 
     /> 
+0

'х: Bind' не удается скомпилировать как только я установить' Mode = OneWay'. Одноразовая привязка не то, что мне нужно ... – Yarik

+0

Не знал, что вам нужно использовать ** Mode = OneWay **. Обновленный ответ будет более полным и позволит использовать другие режимы. – user5606561

+0

1. 'Mode = OneWay' - это режим по умолчанию для' Binding' (в отличие от упомянутого вами 'x: Bind', который по умолчанию имеет' Mode = OneTime'). 2. Что вы подразумеваете под ** ReferenceSource **? – Yarik

Смежные вопросы