Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Обработчик событий системы в своём классе


Автор: Stolzen 22.5.2010, 01:03
Доброе время суток!

Столкнулся со следующей проблемой:
Есть объект TreeView, который, как известно, содержит в себе коллекцию Nodes.
Объекты Node там очень разные, и при клике на них должны вести себя по-разному.
Самое логичное решение, пришедшее мне в голову - создать производные от класса TreeNode и объявить в них событие Click (в моем случае это DoubleClick).

Вот один из примеров:

Код

    public class MyTreeNode : System.Windows.Forms.TreeNode
    {

        public event System.EventHandler DoubleClick;

        protected void OnDoubleClick(System.EventArgs e)
        {
            if (DoubleClick != null)
            {
                DoubleClick(this, e);
                System.Windows.Forms.MessageBox.Show("тест1");
            }
        }
    }


Код

                MyTreeNode node = new MyTreeNode();
                node.Tag = rdrGoods.GetValue(0);
                node.Text = rdrGoods.GetValue(2).ToString() + " (" + rdrGoods.GetValue(3).ToString() + ")";
                treeView1.Nodes[j].Nodes.Add(node);
                node.DoubleClick += new EventHandler(node_DoubleClick);


Код

        private void node_DoubleClick(object sender, EventArgs e)
        {
            System.Windows.Forms.MessageBox.Show("тест2");
        }


Естественно, ничего не работает. Ни окошка с "тест1", ни окошка с "тест2" я так и не увидел.

В Делфи я бы стал отлавливать сообщения Windows, которые бы мне говорили, что по объекту был сделан дабл-клик. Поиск в гугле с запросом "обработка классами сообщений системы" и кучей различных его вариаций ничего не дал. 

Может, кто-нибудь что-то посоветует? 
Да и вообще, было бы интересно узнать, как цеплять обработчики событий системы к классам, которые не являются потомками Control.

Автор: CYBERDREAM 22.5.2010, 12:49
Привет Stolzen, Как по мне, то лучше сделать следующим образом. 
Как ты  сказал, у тебя в узлах разные данные хранятся, вот как пример
Код

 public abstract class Data//Данные хранящиеся в узлах дерева
    {
        public String Caption { get; set; }

        protected Data(String caption)
        {
            Caption = caption;
        }
        public abstract void RaiseDoubleClick();
    }

    public class Sun:Data
    {
        public Sun(string caption) : base(caption)
        {
        }

        public override void RaiseDoubleClick()
        {
            MessageBox.Show(string.Format("Even rose in Sun object.{0}Caption: {1}", Environment.NewLine, Caption));
        }
    }
    public class Moon:Data
    {
        public Moon(string caption)
            : base(caption)
        {
        }

        public override void RaiseDoubleClick()
        {
            MessageBox.Show(string.Format("Even rose in Moon object.{0}Caption: {1}", Environment.NewLine, Caption));
        }
    }

    public class Star : Data
    {
        public Star(string caption)
            : base(caption)
        {
        }

        public override void RaiseDoubleClick()
        {
            MessageBox.Show(string.Format("Even rose in Star object.{0}Caption: {1}", Environment.NewLine, Caption));
        }
    }


В своей форме при добавлении закидывай в тэги объекты 
Код

            treeView1.Nodes.Add("Object 1").Tag = new Sun("Dream");
            treeView1.Nodes.Add("Object 2").Tag = new Moon("Незабудка");
            treeView1.Nodes.Add("Object 3").Tag = new Star("Dream");


а обработчик уже выглядит так
Код

 private void treeView1_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            if (e.Node.Tag is Data)
                ((Data) e.Node.Tag).RaiseDoubleClick();
        }

Думаю так по красивее будет, и легче

Автор: Stolzen 23.5.2010, 00:19
Спасибо CYBERDREAM!

Я уже что-то подобное наваял

Код

        private void treeView1_DoubleClick(object sender, EventArgs e)
        {
            if (treeView1.SelectedNode is ItemTreeNode)
            {
                ItemTreeNode node = (ItemTreeNode)treeView1.SelectedNode;
                AddItemIntoCurrent(node.ItemKey);
            }

        ...

        }


Хотя ваше решение элегантнее, но, в принципе, суть та же - используется обработчик событий компонента treeView1.

Может всё-же есть возможность ноду быть независимым от TreeView и самому реагировать на события?

Автор: CYBERDREAM 23.5.2010, 08:02
А как ты отследишь дабл клик по узлу? никак, так что выйдет.
Думаю логичнее будет мой споосб использовать

Автор: diadiavova 23.5.2010, 09:51
Цитата(Stolzen @  23.5.2010,  01:19 Найти цитируемый пост)
Может всё-же есть возможность ноду быть независимым от TreeView и самому реагировать на события?

Узел не явяется контролом, так что, независимо от того, что использовать, встроенные механизмы или делать через жо винапи - это всё-равно можно реализовать только через тривью. Фактически узлы просто содержат информацию о том, как дерево должно себя прорисовывать. 

Но реализовать клики в самих узлах можно. Для этого надо создать производный от TreeNode класс и отслеживать в нём нужное тебе событие дерева. Тут правда есть нюанс: узел как объект может существовать и вне дерева, поэтому инициировать отслеживание событий дерева придётся после того, как узел будет в это дерево добавлен, вручную. Короче гемор тот ещё. 
 В общем если очень сильно надо, то набросок кода привожу
Код

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            var n1 = new ClickableTreeNode();
            n1.Text = "qwerty";
            this.treeView1.Nodes.Add(n1);
            n1.ListenTreeEvents();
            n1.DoubleClick += new EventHandler(n_DoubleClick);
            var n2 = new ClickableTreeNode();
            n2.Text = "йцукен";
            this.treeView1.Nodes.Add(n2);
            n2.ListenTreeEvents();
            n2.DoubleClick += new EventHandler(n_DoubleClick2);
        }

        void n_DoubleClick(object sender, EventArgs e)
        {
            MessageBox.Show((sender as ClickableTreeNode).Text);
        }
        void n_DoubleClick2(object sender, EventArgs e)
        {
            MessageBox.Show("Текст узла: " + (sender as ClickableTreeNode).Text);
        }
    }
    public class ClickableTreeNode : TreeNode
    {

        public void ListenTreeEvents()
        {
            this.TreeView.NodeMouseDoubleClick += new TreeNodeMouseClickEventHandler(TreeView_NodeMouseDoubleClick);
        }
        public event EventHandler DoubleClick;
        void TreeView_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            if (DoubleClick != null && e.Node == this) DoubleClick(this, new EventArgs());
        }
    }
Но вообще - не советую smile

Автор: Stolzen 23.5.2010, 23:03
Цитата(CYBERDREAM @  23.5.2010,  16:02 Найти цитируемый пост)
А как ты отследишь дабл клик по узлу? никак, так что выйдет.

Да, так и получается, что никак не выходит отследить событие самим узлом. Хотя наверняка способ есть - но я так и не смог научится ставить хуки своим классам для отлова событий Windows. Да и не .NET это уже получается  smile 

Цитата(diadiavova @  23.5.2010,  17:51 Найти цитируемый пост)
В общем если очень сильно надо, то набросок кода привожу

Спасибо, diadiavova! Думаю, я оставлю у себя вариант, предложенный CYBERDREAM, но и ваш пример мне тоже пригодится.

Автор: diadiavova 24.5.2010, 10:41
Цитата(Stolzen @  24.5.2010,  00:03 Найти цитируемый пост)
Хотя наверняка способ есть - но я так и не смог научится ставить хуки своим классам для отлова событий Windows. Да и не .NET это уже получается 

А почему надо отслеживать событие самим узлом? Это ведь неудобно. Стандартный способ ведь очень удобен. В обработчике события NodeMouseDoubleClick самого дерева просто надо проверять по какому узлу кликнули, этот узел будет возвращён свойством Node второго аргумента обработчика. Зачем все эти пляски с бубнами? smile 

Автор: CYBERDREAM 24.5.2010, 11:51
Цитата(diadiavova @ 24.5.2010,  10:41)
Зачем все эти пляски с бубнами? smile

иногда программисту это надо (отвести душу так сказать)  smile 

Автор: diadiavova 24.5.2010, 11:58
Ну разве что...

Автор: Stolzen 24.5.2010, 23:19
Не всегда решения, приходящие мне в голову, являются логичными. И порой они труднореализуемы smile

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