Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Разработка Windows Forms > Добавление ноды в TreeView и в XML одновременно.


Автор: valzy 20.11.2008, 12:19
Собственно, нужно чтобы при добавлении ноды в TreeView обновлялся документ XML.
TreeView связан с XML документом таким образом, что TreeView строится из XML-документа. Соответственно при добавлении в TreeView документ XML должен обновляться.
Строить XML на основе TreeView это плохое решение. Кто-нибудь знает конкретные методы решения подобной проблемы? Напишите, плиз, буду очень благодарен.

Автор: Rififi 20.11.2008, 12:22
Сделать свой контрол на основе TreeView, в котором синхронизировать обновление

Автор: valzy 20.11.2008, 12:44
Цитата(Rififi @ 20.11.2008,  12:22)
Сделать свой контрол на основе TreeView, в котором синхронизировать обновление

С чего нужно примерно начать и как синхронизировать? Понятия "Абсолютного индекса" для TreeView здесь уже нет. Я на dotnet недавно, нужна помощь...

Автор: diadiavova 20.11.2008, 13:54
А можно небольшое уточнение? Почему

Цитата(valzy @  20.11.2008,  12:19 Найти цитируемый пост)
Строить XML на основе TreeView это плохое решение.


ИМХО: оно самое лучшее. Вопрос в том, как оно будет реализовано.

Автор: valzy 21.11.2008, 09:39
нужно чтобы дерево вида
+<object>
|
|---+<table>
|    |---+ATTRIBUTE: width
|    |     |---VALUE: 100
|    |
|    |---+ATTRIBUTE: height
|    |     |---VALUE: 70
|    |
|    |---+<object>
|          |---+<cabinet>
|                |---+ATTRIBUTE: count
|                      |---VALUE: 3
|    
|---+<table>
      |---+ATTRIBUTE: width
            |---VALUE: 120


было сгенерировано в xml вида
<object>
  <table width="100" height="70">
     <object>
         <cabinet count="3"/>
     </object>
  </table>
  <table width="120" />
</object>


Автор: diadiavova 21.11.2008, 12:39
Да всё очень просто: как сам TreeView так и его TreeNode'ы могут быть унаследованы. Создай несколько своих нодов, ну например нод, который будет сохраняться как элемент, и нод, который будет сохраняться как атрибут для остальных типов узлов можно сделать то же самое, кроме того, каждому можно добавить методы и свойства, благодаря которым каждый узел будет правильно генерировать узел документа.


Автор: valzy 21.11.2008, 13:02
Цитата(diadiavova @ 21.11.2008,  12:39)
Да всё очень просто: как сам TreeView так и его TreeNode'ы могут быть унаследованы. Создай несколько своих нодов, ну например нод, который будет сохраняться как элемент, и нод, который будет сохраняться как атрибут для остальных типов узлов можно сделать то же самое, кроме того, каждому можно добавить методы и свойства, благодаря которым каждый узел будет правильно генерировать узел документа.

Оригинально smile а как наследовать ноды?
Примерно я понял, если бы можно было бы, хотелось бы увидеть простенький пример, я недавно с dotNet-ом работаю...

Автор: shmarov 21.11.2008, 13:38
к примеру - ноды наследовать вот так:
Код

public class SimpleTreeNode : System.Windows.Forms.TreeNode
    {
        int _id;
        string _alterText;

        public SimpleTreeNode(string Text, int ID)
        {
            this.Text = Text;
            _id = ID;
        }

        public string AlternativeText
        {
            set
            {
                _alterText = value;
            }
            get
            {
                return _alterText;
            }
        }

        /// <summary>
        /// Идентификатор
        /// </summary>
        public int ID
        {
            set
            {
                _id = value;
            }
            get
            {
                return _id;
            }
        }
    }


ну а дальше - наследуй TreeView и в методах изменения ноды генери свой XML

Как вариант - я расширял TreeView свойством DataSource, в котором в нужной мне форме хранил данные и разбирал их соответственно. А у DataSet, который можно указать в качестве значения для DataSource-a, есть метод сохранения XML. Вопрос только подойдёт ли тебе такой подход по структуре получаемого файла.

Автор: diadiavova 21.11.2008, 20:24
Ну, вообще-то можно всё сделать более удобным. Просто я уже почти сделал и тут у меня свет вырубило, а сохранить не успел, так что: если потерпишь малость то сделаю потом примерчик(если, конечно вопрос ещё актуален).

Автор: diadiavova 21.11.2008, 23:26
Ну вот тут проектик надросал.

Автор: valzy 24.11.2008, 07:20
Благодарю! Не код, а произведение искусства! 

Автор: valzy 25.11.2008, 08:20
А если XML-ка содержит контент, ну т.е. текст:
<object>
  <content>Столы<br />Шкафчики
    <table width="100" height="70">
       <object>
           <cabinet count="3"/>
       </object>
    </table>
    <table width="120" />
  </content>
</object>

то как с этим текстом поступить? я просто проверял тип ноды на соответствие XmlNodeType.Text.
Если по сорцам diadiavova смотреть, то вот так я изменил (изменения кода см. в блоке комментариев //---):

Код

public class ElementNode : XmlTreeNode
    {
        #region Constructors

        public ElementNode(XmlElement element)
        {
            this.Name = element.Name;
            this.Text = "<" + this.Name + ">";
            foreach (XmlAttribute at in element.Attributes)
            {
                this.Nodes.Add(new AttributeNode(at));
            }
            foreach (XmlNode n in element.ChildNodes)
            {
                // ----------------------------------------------------------------------------------
                // Content parsing.
                if (n is XmlElement)
                    this.Nodes.Add(new ElementNode((XmlElement) n));
                else
                {
                    // If we are have the object "content".
                    if (n.NodeType == XmlNodeType.Text)
                        this.Nodes.Add("#text", n.InnerText);
                // ----------------------------------------------------------------------------------
                }
            }
        }

        #endregion
...

Автор: diadiavova 25.11.2008, 12:53
Обрати внимание на то, что некоторые коды я в своём примере не использовал вообще(хотя сам же и написал их). Например: создал абстрактный класс для всех узлов, в нём есть свойство, показывающее тип узла, которое я ни разу не использовал. Всё это делалось для того, чтобы модель можно было расширить при необходимости. Если тебе нужно включить в модель текстовый блок, блок CDATA, инструкцию приложения, или к примеру элемент, который должен вести себя по-другому - всё это можно организовать путём наследования от абстрактного класса XmlTreeNode.
Естественно: Некоторых изменений это потребует и в существующих классах, но они незначительны.

Вот так примерно должен выглядеть текстовый узел
Код

    public class TextNode : XmlTreeNode
    {
      
        public TextNode(XmlText node)
        {
            this.Text = node.Name;
            this.TextValue = node.Value;
        }

        public override XmlNodeType XmlNodeType
        {
            get 
            {
                return XmlNodeType.Text;
            }
        }

        public override XmlNode GetXmlNode(XmlDocument dock)
        {
            return (XmlNode)GetXmlTex(dock);
        }

        public XmlText GetXmlTex(XmlDocument dock)
        {
            return dock.CreateTextNode(this.TextValue);
        }

        string _textValue = string.Empty;
        public string TextValue
        {
            get
            {
                return _textValue;
            }
            set
            {
                _textValue = value;
            }
        }


Естественно, что он будет отображать - решать тебе, в таком виде в дереве просто будет написано #text, нужно что-то другое - пропиши это в конструкторе.


Кроме того, в конструкторе ElementNode надо указать, что если узел документа является текстовым, то надо формировать соответствующий элемент.

Код

  public ElementNode(XmlElement element)
        {
            this.Name = element.Name;
            this.Text = "<" + this.Name + ">";
            foreach(XmlAttribute at in element.Attributes)
            {
                this.Nodes.Add(new AttributeNode((XmlAttribute)at));
            }
            foreach (XmlNode n in element.ChildNodes)
            {
          XmlTreeNode newNode=null;
                switch(n.NodeType)
                {
                    case XmlNodeType.Element:
                newNode=new ElementNode((XmlElement)n);
                break;
                    case XmlNodeType.Text:
                newNode = new TextNode((XmlText)n);
                break;
                
                }
                try
                {
                    this.Nodes.Add(newNode);
                }
                catch 
                {
                
                }

            }
        }

Примерно так. Код не проверял, но если идея ясна, то возможные ошибки исправишь сам.

Автор: valzy 26.11.2008, 07:51
 smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)