WPF, привязка данных XML в зависимые / каскадные ComboBox - PullRequest
1 голос
/ 02 августа 2010

У меня есть XML-файл со следующей структурой:

<Products>
  <Product name="MyProduct1">
    <Components>
      <Component name="MyComponent1">
        <SubComponents>
          <SubComponent name="MySubComponent1"/>
          <SubComponent name="MySubComponent2"/>
          ...more SubComponent nodes...
        </SubComponents>
      </Component>
      ...more Component nodes...
    </Components>
  </Product>
  ...more Product nodes...
</Products>

Я пытаюсь создать приложение WPF, в котором есть поле со списком продуктов. Я совершенно новичок в WPF, поэтому я не знаю, правильно ли я поступаю. Когда выбран Продукт, второй ComboBox должен быть заполнен всеми Компонентами для этого Продукта. И когда выбран Компонент, третий ComboBox должен быть заполнен всеми Подкомпонентами для этого Компонента.

Я не знаю, как установить зависимость между ComboBox, за исключением заполнения зависимого ComboBox внутри обработчика событий, запускаемого независимым ComboBox. Кажется, это означает, что мне нужно иметь возможность читать XML в C #, поэтому у меня есть [Serializable] классов для Products, Product, Component и SubComponent. Однако я пытался сделать привязку данных XML в моем XAML:

<Window.Resources>
    <XmlDataProvider Source="Products.xml"
                     XPath="Products/Product"
                     x:Key="productsXml"/>
</Window.Resources>

В настоящее время я не вижу списка названий продуктов в моем первом ComboBox, XAML которого выглядит следующим образом:

<ComboBox Height="23" HorizontalAlignment="Left" Margin="138,116,0,0"
          Name="cbo_product" VerticalAlignment="Top" Width="120"
          ItemsSource="{Binding Source=productsXml, XPath=@name}"
          SelectionChanged="product_SelectionChanged"/>

Продукты XML должны быть доступны только для чтения - пользователь не сможет изменять какие-либо значения в XML из приложения. Я просто хочу прочитать данные XML и отобразить их в приложении.

У меня есть несколько вопросов:

  1. Правильно ли я поступаю? Наличие отдельного XML-файла, из которого читает мое приложение WPF, наличие [Serializable] классов, представляющих узлы в XML-файле с целью извлечения данных из этих узлов в C #, использование обработчика событий для кодирования зависимостей между ComboBox и т. Д.
  2. Почему названия моих продуктов, например, MyProduct1, не отображаются в моем ComboBox? В настоящее время он просто отображается пустым.
  3. Кажется, что почти * классы [Serializable] для представления моих узлов XML являются избыточными / ненужными, поскольку в XAML уже есть XmlDataProvider / XPath. Это тот случай?

Edit:

Обновил мой ComboBox XAML до следующего, и теперь я вижу свой список названий продуктов в ComboBox, благодаря ответу дециклона :

<ComboBox Height="23" HorizontalAlignment="Left" Margin="138,116,0,0"
          Name="cbo_product" VerticalAlignment="Top" Width="120"
          ItemsSource="{Binding Source={StaticResource productsXml}}"
          DisplayMemberPath="@name"
          SelectionChanged="product_SelectionChanged"/>

Ответы [ 2 ]

2 голосов
/ 02 августа 2010

Хорошо, так как я нашел ответ на мой более конкретный вопрос , я думаю, что знаю и ответ на этот вопрос. Мне не нужны [Serializable] классы для разных узлов в моем XML, потому что я могу просто использовать XAML и XPath для создания каскадных / зависимых ComboBox:

<!-- Independent -->
<ComboBox Height="23" HorizontalAlignment="Left" Margin="138,116,0,0"
          Name="cbo_product" VerticalAlignment="Top" Width="120"
          ItemsSource="{Binding Source={StaticResource productsXml}}"
          DisplayMemberPath="@name"/>

<!-- Dependent -->
<ComboBox Height="23" HorizontalAlignment="Left" Margin="138,151,0,0"
          Name="cbo_component" VerticalAlignment="Top" Width="201"
          DataContext="{Binding ElementName=cbo_product, Path=SelectedItem}"
          ItemsSource="{Binding XPath=Components/Component}"
          DisplayMemberPath="@name"/>
2 голосов
/ 02 августа 2010

Свойство ItemsSource должно быть установлено для набора элементов, которые должны отображаться в списке, который в вашем случае равен XmlDataProvider.Пользователь StaticResource, чтобы найти его, поскольку он определен как ресурс.Свойство DisplayMemberPath должно использоваться для выбора того, какое свойство следует использовать для отображения текста в выпадающем списке.

Что касается вашего 1-го (и 3-го) вопроса, мне лично больше нравится создавать классы, чем использовать необработанный XML.Это дает мне несколько преимуществ, таких как

  • Добавление свойств оболочки.Например, свойство FullName = FirstName + "" + LastName.

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

  • Я могу добавить свое собственное поведение в качестве методов, которые могут быть действительно полезны для выполнения небольших задач.

  • Управление методом сериализации и внедрение собственной логикив нем используются атрибуты.

Дело в том, стоит ли оно того?Вы действительно заботитесь об этих преимуществах?Это все равно что выбирать между DataReader и DataSet.Для целей только для чтения и отображения используйте сырой XML, а если вы собираетесь много с ним играть, используйте классы.

...