Связывание ComboBox с LINQ XML - PullRequest
4 голосов
/ 26 февраля 2010

Извините за мой плохой английский, это не мой родной язык.

Я новичок (с 3-х дней) с WPF и LINQ, и обычный пользователь C #.

Вчера я целый день пытался решить мою проблему и прочитал несколько документов, но ошибка в моем коде сохраняется.

Я передаю XElement элементу управления, который связывает его содержимое, но у меня есть но в ComboBox

Вот XML-код XElement:

<racine>
    <element nom="Element 1">
      <rubrique nom="Element 1 - rubrique 1">
        <etat valeur="Hors service">
          <option valeur="En service" />
          <option valeur="Hors service service" />
        </etat>
        <observation>lorem ipsum</observation>
      </rubrique>
      <rubrique nom="Element 1 - rubrique 2">
        <etat>
        </etat>
        <observation>titi toto</observation>
      </rubrique>
    </element>
    <element nom="Element 2">
      <rubrique nom="Element 2 - rubrique 1">
        <etat valeur="foo">
        </etat>
        <observation>youpi</observation>
      </rubrique>
      <rubrique nom="Element 2 - rubrique 2">
        <etat valeur="bar">
          <option valeur="En service" />
        </etat>
        <observation></observation>
      </rubrique>
    </element>
</racine>

Вот код моего элемента управления MonControle.xaml.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml.Linq;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Collections.Specialized;

namespace MonProjet.Controles
{
    /// <summary>
    /// Logique d'interaction pour MonControle.xaml
    /// </summary>
    public partial class MonControle : UserControl
    {
        XElement xRacine;

        ObservableCollection<XElement> xElementsObservable = new ObservableCollection<XElement>();

        public MonControle()
        {
            InitializeComponent();
            DataContext = xElementsObservable;
        }

        #region Propriété Attribus
        [Category("Configuration"), Browsable(false), Description("Element XML racine")]
        public XElement xRacine
        {
            get
            {
                return xRacine;
            }
            set
            {
                this.xRacine = value;
                MajXElementsObservable();

            }
        }
        #endregion

        private void MajXElementsObservable()
        {
            var requette = from xElements in xRacine.Descendants("element")
                           select (XElement)xElements;
            xElementsObservable.Clear();
            foreach (XElement xElement in requette)
            {
                xElementsObservable.Add(xElement);
            }
        }

    }
}

И вот xaml для MonControle.xaml:

<UserControl x:Class="MonProjet.Controles.MonControle"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="Auto" Width="Auto">
    <!--
    http://www.youdev.net/post/2008/09/23/WPF-SplitContainer-2.aspx
    http://www.youdev.net/post/2009/03/19/WPF-SplitContainer-Part-2.aspx
    -->
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="25*"/>
            <ColumnDefinition Width="Auto" MinWidth="4"/>
            <ColumnDefinition Width="75*"/>
        </Grid.ColumnDefinitions>
        <DockPanel Grid.Column="0" LastChildFill="True">
            <ListBox Name="lbxElements" ItemsSource="{Binding UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="Attribute[nom].Value" />
        </DockPanel>
        <GridSplitter Grid.Column="1" ResizeBehavior="PreviousAndNext" Width="4" VerticalAlignment="Stretch"/>
        <DockPanel Grid.Column="2" LastChildFill="True" DataContext="{Binding Path=SelectedItem.Elements[rubrique], ElementName=lbxElements, UpdateSourceTrigger=PropertyChanged}">
            <ListBox ItemsSource="{Binding UpdateSourceTrigger=PropertyChanged}"
                     IsSynchronizedWithCurrentItem="True">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <GroupBox Header="{Binding Path=Attribute[nom].Value}">
                            <StackPanel Orientation="Horizontal">
                                <!-- /404937/privyazka-wpf-combobox-k-polzovatelskomu-spisku -->
                                <ComboBox MinWidth="75" IsEditable="True"
                                          ItemsSource="{Binding Path=Element[etat].Elements[option], UpdateSourceTrigger=PropertyChanged}"
                                          DisplayMemberPath="Attribute[valeur].Value"
                                          SelectedValuePath="Attribute[valeur].Value" 
                                          SelectedValue="{Binding Path=Element[etat].Element[option].Attribute[valeur].Value}"
                                          />
                                <TextBox MinWidth="150" AcceptsReturn="False" AcceptsTab="False" TextWrapping="NoWrap"
                                         Text="{Binding Path=Element[observation].Value, UpdateSourceTrigger=PropertyChanged}" />
                            </StackPanel>
                        </GroupBox>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </DockPanel>
    </Grid>
</UserControl>

Мои вопросы:

  • При контрольной нагрузке все нормально, но если я переключу между элементом в оставил ListBox, значение ComboBox изменить ... попробовать много, много сделать теста, но это невозможно исправить!

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

  • И последнее, но не менее важное: я хочу подняться событие, когда ObservableCollection изменено для записи файла XML, но невозможно поймать событие ... Я пробовал что-то вроде xElementsObservable.CollectionChanged + = new NotifyCollectionChangedEventHandler (XElementsObservable_CollectionChanged); но это не работает ...

Заранее спасибо за помощь!

1 Ответ

3 голосов
/ 03 марта 2010

Это было сложно, но у меня есть решение всех моих вопросов!

вот решение:

В первый раз ComboBox XAML должен выглядеть так:

<ComboBox MinWidth="75" IsEditable="True"
          IsSynchronizedWithCurrentItem="False"
          ItemsSource="{Binding Path=Element[etat].Elements[option]}"
          DisplayMemberPath="Attribute[valeur].Value"
          Text="{Binding Element[etat].Attribute[valeur].Value, UpdateSourceTrigger=PropertyChanged}"
          />

Это ответ на вопрос 1 и 2: поскольку мы фокусируемся на значении атрибута "valeur" узла, который содержит, мы можем написать то, что хотим, даже если значение, которое мы пишем, отсутствует вколлекция, и проблема отображения узлов в тексте ComboBox исчезла!

По вопросу 3 моя ошибка в том, что я сфокусировался на наблюдаемой коллекции!

Но решение простоеЯ прикрепил событие «Изменено» к XDocument, который содержит все элементы XE, которыми я управляю здесь!

Итак, я поместил этот код в главное окно моего программного обеспечения:

  private void InitPerso()
    {

        xDoc = XDocument.Load(@"C:\fichier.xml");

        xDoc .Changed += new EventHandler<XObjectChangeEventArgs>(XDoc_Changed);

    }

    private void XEdls_Changed(object sender, XObjectChangeEventArgs e)
    {
        xDoc .Save(@"C:\fichier.xml");
    }

Etвуаля!

Извините за плохой английский, надеюсь, это поможет ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...