Каскадные поля со списками (списки для выбора)

Создание нескольких полей со списками (также называемых списками выбора) для диалоговых окон Data Standard, где следующее поле со списком зависит от выбора, сделанного в первом поле.

При выборе значения в одном поле в следующем поле должны отображаться значения с учетом варианта, выбранного в предыдущем поле. Предположим, имеется два поля со списками: в одном отображаются наименования производителей автомобилей (BMW, Mercedes, Ferrari и т. д.), а во втором — модели автомобилей для выбранного производителя (для BMW — 1, 2, 5, X2, X5, для Mercedes — A, B, C, CL, CLS и т. д.).

Шаг 1. Создание источника данных

Чтобы заполнить поля со списком, потребуется источник, из которого будут поступать данные. Поскольку в WPF используется внутренний механизм XML, можно создать файл XML, который будет содержать данные. В файле XML для первых вариантов выбора используется содержимое первого уровня. Каждая запись имеет дочерние записи, содержащие вторые варианты выбора. Эти записи второго уровня также могут иметь дочерние элементы в случае, если требуется создать списки для выбора трех или более уровней. Это выглядит следующим образом:

Создайте файл data.xml, скопируйте в него это содержимое и сохраните его в одной папке с файлом XAML, куда требуется добавить каскадные поля со списками (например, в папку C:\ProgramData\Autodesk\Vault <номер версии>\Extensions\DataStandard\Vault\Configuration).

Шаг 2

Следующий шаг — добавление файла data.xml в качестве ресурса в файл Data Standard с расширением XAML. Так поля со списками смогут использовать данные.
  1. Добавьте следующие строки в файл XAML в разделе ресурсов:
    <XmlDataProvider x:Key="comboDataSource"
    Source="C:\ProgramData\Autodesk\Vault 2016\Extensions\DataStandard\Vault\Configuration\data.xml"/>
    
    Таким образом, весь раздел ресурсов будет выглядеть следующим образом:
    <prop:dsWindow.Resources xmlns:prop="clr-namespace:dataStandard.UI.View;assembly=dataStandard.UI">
    ...
    ......
    ....
    <XmlDataProvider x:Key="comboDataSource" Source="C:\ProgramData\Autodesk\Vault 2016\Extensions\DataStandard\Vault\Configuration\data.xml"/>
    </prop:dsWindow.Resources>

    Как видно, новому ресурсу было присвоено имя comboDataSource, а путь ведет к файлу data.xml.

Шаг 3

Теперь следует создать поля со списками и настроить их так, чтобы они указывали на данные первого уровня в файле XML и на соответствующий второй уровень. Далее представлен пример первого поля со списком:
<ComboBox x:Name="ComboCarCompanies" Grid.Column="1" Grid.Row="5" 
  ItemsSource="{Binding Source={StaticResource comboDataSource}, XPath=/Data/Companies/*}"
  Text="{Binding Prop[CarVendor].Value}" DisplayMemberPath="@Name"
  SelectedValue="{Binding Prop[CarVendor].Value}" SelectedValuePath="@Name" />

В рассматриваемом примере поле со списками ComboCarCompanies расположено в столбце 1, строка 5. Источник содержимого для этого поля со списком находится в ресурсе с именем comboDataSource. XPath указывает на верный путь для чтения содержимого. Все данные помещены в элемент Companies. Дочерние элементы элемента Companies содержат по одному элементу, каждый с именем Name. Таким образом, атрибуты DisplayMemberPath и SelectedValuePath указывают на @Name. Атрибуты Text и SelectedValue указывают на свойство, которое заполняется значением, выбранным пользователем.

  1. После внесения изменений следует сохранить файл и просмотреть диалоговое окно. В первом поле со списком должны отображаться верные значения.

    Второе поле со списком выглядит аналогично первому. Единственное отличие заключается в том, что источник данных поступает из первого поля со списком. Пользователь выбирает один узел из файла XML. Узел загружается как выбранный элемент в первом поле со списком. Узлу также известны дочерние элементы выбранного элемента.

  2. Настройте второе поле со списком для указания на выбранный элемент в первом поле со списком и используйте дочерние значения для отображения. Пример кода:
    <ComboBox x:Name="ComboCarType" Grid.Column="1" Grid.Row="6"
    ItemsSource="{Binding SelectedItem, ElementName=ComboCarCompanies}"
    Text="{Binding Prop[CarType].Value}" DisplayMemberPath="@Type"
    SelectedValue="{Binding Prop[CarType].Value}"
    SelectedValuePath="@Type"/>
    

    Большинство атрибутов в данном примере выполняют ту же функцию, что и первое поле со списком. Отличие заключается в элементе ItemSource. В этом примере первое поле со списками ComboCarCompanies указывает на элемент SelectedItem.

  3. Сохраните изменения и просмотрите диалоговое окно.