Заметка
Доступ к этой странице требует авторизации. Вы можете попробовать войти в систему или изменить каталог.
Доступ к этой странице требует авторизации. Вы можете попробовать сменить директорию.
Во всех предыдущих примерах привязки данных в свойстве Path класса Binding (или свойстве Path расширения разметки Binding) указывалось одно свойство. В действительности Path может указывать на вложенное свойство (свойство свойства) или элемент коллекции.
Например, предположим, что страница содержит объект TimePicker:
<TimePicker x:Name="timePicker">
Свойство Time класса TimePicker имеет тип TimeSpan, но, возможно, вам нужно создать привязку данных, которая ссылается на свойство TotalSeconds этого значения TimeSpan. Вот эта привязка данных:
{Binding Source={x:Reference timePicker},
Path=Time.TotalSeconds}
Свойство Time имеет тип TimeSpan, который имеет свойство TotalSeconds. Свойства Time и TotalSeconds соединяются точкой. Элементы в строке Path всегда ссылаются на свойства, а не на их типы.
Этот и еще ряд примеров представлены на странице Path Variations (Варианты пути):
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:globe="clr-namespace:System.Globalization;assembly=netstandard"
x:Class="DataBindingDemos.PathVariationsPage"
Title="Path Variations"
x:Name="page">
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType="Label">
<Setter Property="FontSize" Value="Large" />
<Setter Property="HorizontalTextAlignment" Value="Center" />
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout Margin="10, 0">
<TimePicker x:Name="timePicker" />
<Label Text="{Binding Source={x:Reference timePicker},
Path=Time.TotalSeconds,
StringFormat='{0} total seconds'}" />
<Label Text="{Binding Source={x:Reference page},
Path=Content.Children.Count,
StringFormat='There are {0} children in this StackLayout'}" />
<Label Text="{Binding Source={x:Static globe:CultureInfo.CurrentCulture},
Path=DateTimeFormat.DayNames[3],
StringFormat='The middle day of the week is {0}'}" />
<Label>
<Label.Text>
<Binding Path="DateTimeFormat.DayNames[3]"
StringFormat="The middle day of the week in France is {0}">
<Binding.Source>
<globe:CultureInfo>
<x:Arguments>
<x:String>fr-FR</x:String>
</x:Arguments>
</globe:CultureInfo>
</Binding.Source>
</Binding>
</Label.Text>
</Label>
<Label Text="{Binding Source={x:Reference page},
Path=Content.Children[1].Text.Length,
StringFormat='The second Label has {0} characters'}" />
</StackLayout>
</ContentPage>
Во втором элементе Label источником привязки является сама страница. Свойство Content имеет тип StackLayout, который имеет свойство Children типа IList<View>. Этот тип, в свою очередь, имеет свойство Count, в котором указывается число дочерних объектов.
Пути с индексаторами
Привязка в третьем элементе Label на странице Path Variations ссылается на класс CultureInfo в пространстве имен System.Globalization:
<Label Text="{Binding Source={x:Static globe:CultureInfo.CurrentCulture},
Path=DateTimeFormat.DayNames[3],
StringFormat='The middle day of the week is {0}'}" />
В качестве источника задано статическое свойство CultureInfo.CurrentCulture, представляющее собой объект типа CultureInfo. В этом классе определено свойство DateTimeFormat типа DateTimeFormatInfo, содержащее коллекцию DayNames. Индекс выбирает четвертый элемент.
Четвертый элемент Label выполняет схожие действия, но для французского языка и региональных параметров. Свойству Source привязки присваивается объект CultureInfo с конструктором:
<Label>
<Label.Text>
<Binding Path="DateTimeFormat.DayNames[3]"
StringFormat="The middle day of the week in France is {0}">
<Binding.Source>
<globe:CultureInfo>
<x:Arguments>
<x:String>fr-FR</x:String>
</x:Arguments>
</globe:CultureInfo>
</Binding.Source>
</Binding>
</Label.Text>
</Label>
Дополнительные сведения об указании аргументов конструктора в XAML см. в разделе Передача аргументов конструктора.
Наконец, последний пример аналогичен второму, за тем исключением, что он ссылается на один из дочерних элементов StackLayout:
<Label Text="{Binding Source={x:Reference page},
Path=Content.Children[1].Text.Length,
StringFormat='The first Label has {0} characters'}" />
Этот дочерний объект представляет собой элемент Label, который имеет свойство Text типа String, имеющего свойство Length. Первый элемент Label сообщает значение TimeSpan, заданное в TimePicker, поэтому при изменении текста итоговый элемент Label также меняется.
Вот работающая программа:
Отладка сложных путей
Составлять определения сложных путей может быть непросто: нужно знать тип каждого вложенного свойства или элементов в коллекции, чтобы правильно добавить следующее вложенное свойство. Однако сами типы в пути отсутствуют. Один из приемов — формировать путь поэтапно, проверяя промежуточные результаты. В последнем примере можно было начать без определения Path:
<Label Text="{Binding Source={x:Reference page},
StringFormat='{0}'}" />
Этот код отображает тип источника привязки (DataBindingDemos.PathVariationsPage). Известно, что страница PathVariationsPage является производной ContentPage, поэтому она имеет свойство Content:
<Label Text="{Binding Source={x:Reference page},
Path=Content,
StringFormat='{0}'}" />
Теперь видно, что свойство Content имеет тип Xamarin.Forms.StackLayout. Добавьте свойство Children в Path, и будет ясно, что его тип — Xamarin.Forms.ElementCollection'1[Xamarin.Forms.View]. Это внутренний класс Xamarin.Forms, однако очевидно, что он представляет собой коллекцию. Добавьте индекс. Тип — Xamarin.Forms.Label. Продолжайте тем же образом.
Когда Xamarin.Forms обрабатывает путь привязки, для каждого объекта, реализующего интерфейс PropertyChanged, в пути устанавливается обработчик INotifyPropertyChanged. Например, последняя привязка реагирует на изменение в первом элементе Label, так как меняется свойство Text.
Если свойство в пути привязки не реализует интерфейс INotifyPropertyChanged, изменения этого свойства игнорируются. Некоторые изменения могут сделать путь привязки полностью недействительным, поэтому этот прием следует использовать, только если строка из свойств и вложенных свойств не может стать недействительной.
