Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Во всех предыдущих примерах привязки данных в свойстве 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, изменения этого свойства игнорируются. Некоторые изменения могут сделать путь привязки полностью недействительным, поэтому этот прием следует использовать, только если строка из свойств и вложенных свойств не может стать недействительной.
