Путь привязки Xamarin.FormsXamarin.Forms Binding Path

Скачать пример Скачать примерDownload Sample Download the sample

Во всех предыдущих примерах привязки данных в свойстве Path класса Binding (или свойстве Path расширения разметки Binding) указывалось одно свойство.In all the previous data-binding examples, the Path property of the Binding class (or the Path property of the Binding markup extension) has been set to a single property. В действительности Path может указывать на вложенное свойство (свойство свойства) или элемент коллекции.It's actually possible to set Path to a sub-property (a property of a property), or to a member of a collection.

Например, предположим, что страница содержит объект TimePicker:For example, suppose your page contains a TimePicker:

<TimePicker x:Name="timePicker">

Свойство Time класса TimePicker имеет тип TimeSpan, но, возможно, вам нужно создать привязку данных, которая ссылается на свойство TotalSeconds этого значения TimeSpan.The Time property of TimePicker is of type TimeSpan, but perhaps you want to create a data binding that references the TotalSeconds property of that TimeSpan value. Вот эта привязка данных:Here's the data binding:

{Binding Source={x:Reference timePicker},
         Path=Time.TotalSeconds}

Свойство Time имеет тип TimeSpan, который имеет свойство TotalSeconds.The Time property is of type TimeSpan, which has a TotalSeconds property. Свойства Time и TotalSeconds соединяются точкой.The Time and TotalSeconds properties are simply connected with a period. Элементы в строке Path всегда ссылаются на свойства, а не на их типы.The items in the Path string always refer to properties and not to the types of these properties.

Этот и еще ряд примеров представлены на странице Path Variations (Варианты пути):That example and several others are shown in the Path Variations page:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:globe="clr-namespace:System.Globalization;assembly=mscorlib"
             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 источником привязки является сама страница.In the second Label, the binding source is the page itself. Свойство Content имеет тип StackLayout, который имеет свойство Children типа IList<View>. Этот тип, в свою очередь, имеет свойство Count, в котором указывается число дочерних объектов.The Content property is of type StackLayout, which has a Children property of type IList<View>, which has a Count property indicating the number of children.

Пути с индексаторамиPaths with Indexers

Привязка в третьем элементе Label на странице Path Variations ссылается на класс CultureInfo в пространстве имен System.Globalization:The binding in the third Label in the Path Variations pages references the CultureInfo class in the System.Globalization namespace:

<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.The source is set to the static CultureInfo.CurrentCulture property, which is an object of type CultureInfo. В этом классе определено свойство DateTimeFormat типа DateTimeFormatInfo, содержащее коллекцию DayNames.That class defines a property named DateTimeFormat of type DateTimeFormatInfo that contains a DayNames collection. Индекс выбирает четвертый элемент.The index selects the fourth item.

Четвертый элемент Label выполняет схожие действия, но для французского языка и региональных параметров.The fourth Label does something similar but for the culture associated with France. Свойству Source привязки присваивается объект CultureInfo с конструктором:The Source property of the binding is set to CultureInfo object with a constructor:

<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 см. в разделе Передача аргументов конструктора.See Passing Constructor Arguments for more details on specifying constructor arguments in XAML.

Наконец, последний пример аналогичен второму, за тем исключением, что он ссылается на один из дочерних элементов StackLayout:Finally, the last example is similar to the second, except that it references one of the children of the 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.That child is a Label, which has a Text property of type String, which has a Length property. Первый элемент Label сообщает значение TimeSpan, заданное в TimePicker, поэтому при изменении текста итоговый элемент Label также меняется.The first Label reports the TimeSpan set in the TimePicker, so when that text changes, the final Label changes as well.

Вот работающая программа:Here's the program running:

Варианты путиPath Variations

Отладка сложных путейDebugging Complex Paths

Составлять определения сложных путей может быть непросто. Вам нужно знать тип каждого вложенного свойства или элементов в коллекции, чтобы правильно добавить следующее вложенное свойство. Но сами типы в пути отсутствуют.Complex path definitions can be difficult to construct: You need to know the type of each sub-property or the type of items in the collection to correctly add the next sub-property, but the types themselves do not appear in the path. Один из приемов — формировать путь поэтапно, проверяя промежуточные результаты.One good technique is to build up the path incrementally and look at the intermediate results. В последнем примере можно было начать без определения Path:For that last example, you could start with no Path definition at all:

<Label Text="{Binding Source={x:Reference page},
                      StringFormat='{0}'}" />

Этот код отображает тип источника привязки (DataBindingDemos.PathVariationsPage).That displays the type of the binding source, or DataBindingDemos.PathVariationsPage. Известно, что страница PathVariationsPage является производной ContentPage, поэтому она имеет свойство Content:You know PathVariationsPage derives from ContentPage, so it has a Content property:

<Label Text="{Binding Source={x:Reference page},
                      Path=Content,
                      StringFormat='{0}'}" />

Теперь видно, что свойство Content имеет тип Xamarin.Forms.StackLayout.The type of the Content property is now revealed to be Xamarin.Forms.StackLayout. Добавьте свойство Children в Path, и будет ясно, что его тип — Xamarin.Forms.ElementCollection'1[Xamarin.Forms.View]. Это внутренний класс Xamarin.Forms, однако очевидно, что он представляет собой коллекцию.Add the Children property to the Path and the type is Xamarin.Forms.ElementCollection'1[Xamarin.Forms.View], which is a class internal to Xamarin.Forms, but obviously a collection type. Добавьте индекс. Тип — Xamarin.Forms.Label.Add an index to that and the type is Xamarin.Forms.Label. Продолжайте тем же образом.Continue in this way.

Когда Xamarin.Forms обрабатывает путь привязки, для каждого объекта, реализующего интерфейс INotifyPropertyChanged, в пути устанавливается обработчик PropertyChanged.As Xamarin.Forms processes the binding path, it installs a PropertyChanged handler on any object in the path that implements the INotifyPropertyChanged interface. Например, последняя привязка реагирует на изменение в первом элементе Label, так как меняется свойство Text.For example, the final binding reacts to a change in the first Label because the Text property changes.

Если свойство в пути привязки не реализует интерфейс INotifyPropertyChanged, изменения этого свойства игнорируются.If a property in the binding path does not implement INotifyPropertyChanged, any changes to that property will be ignored. Некоторые изменения могут сделать путь привязки полностью недействительным, поэтому этот прием следует использовать, только если строка из свойств и вложенных свойств не может стать недействительной.Some changes could entirely invalidate the binding path, so you should use this technique only when the string of properties and sub-properties never become invalid.