C# TreeView的使用以及節點的拖動

在項目中需要使用TreeView,TreeView中的節點是需要監控的視頻站點,當拖動TreeView中的節點到Winform中的顯示窗口時,可以實現該節點對應的站點的監控,攝像機轉動等功能。

在實現上述功能之前,程序自定義了一個視頻終端類(Terminal),用來保存每一個監控站點的信息,以及實現連接攝像頭,斷開攝像頭連接,炫動雲臺等操作的接口。

實現思路如下

在FormLoad中加載站點信息,以站點名作爲對應的節點名,並對每一個節點的Tag屬性賦值爲該站點對應的Terminal的對象。


加載完所有站點信息後,TreeView的節點在默認情況下是收縮的,如下圖所示:

爲了能讓節點完全展開,不比在界面上逐一點擊節點,只需在Form_Load事件中添加下邊這句代碼即可:

<span style="font-size:18px;"><span style="white-space:pre">	</span>treeView1.ExpandAll();</span>



顯示效果如下圖:

接下來是實現節點的拖動,將節點拖動到顯示窗口,完成將該節點對應的站點與顯示界面關聯。由於項目設計實驗室成果,不方便公開。在此,以拖動節點到顯示窗口,在顯示窗口完成圖片的顯示爲例。

新建WinForm應用程序,添加TreeView控件和PictureBox控件,將TreeView的AllowDrop屬性設置爲True,PictureBox也有這一屬性,但是在控件的屬性列表中看不見這一屬性,可在代碼中將PictureBox的AllowDrop屬性設置爲True,需要注意的是編譯器不會主動彈出PictureBox的AllowDrop屬性,需要手動將代碼寫完整。將PictureBox的AllowDrop屬性置爲True的代碼如下:

<span style="font-size:18px;"><span style="white-space:pre">	</span>this.pictureBox1.AllowDrop = true;</span>


設計窗體如下:


之後便是手動添加節點,可以在Form_Load事件中完整節點的加載,代碼如下

<span style="font-size:18px;">private void Form1_Load(object sender, EventArgs e)
        {
            if (!treeView1.Nodes.ContainsKey("分組1"))
            {
                TreeNode groupNode1 = new TreeNode("分組1");
                groupNode1.Name = "分組1";
                TreeNode rootNode = treeView1.Nodes.Add("分組1");

                if (!rootNode.Nodes.ContainsKey("節點1"))
                {
                    TreeNode TerminalNode1 = new TreeNode();
                    TerminalNode1.Text = "節點1";

                    rootNode.Nodes.Add(TerminalNode1);
                    string filePath1 = @"F:\壁紙圖標\theDanceNeverEnd.png";
                    TerminalNode1.Tag = filePath1;
                }

                if (!rootNode.Nodes.ContainsKey("節點2"))
                {
                    TreeNode TerminalNode2 = new TreeNode("節點2");
                    TerminalNode2.Name = "節點2";
                    rootNode.Nodes.Add(TerminalNode2);
                    string filePath2 = @"F:\壁紙圖標\cat.jpg";
                    TerminalNode2.Tag = filePath2;
                }
            }

            treeView1.ExpandAll();
        }</span>

這裏用代碼動態創建了一個根節點,兩個子節點,並未每一個子節點的Tag屬性分配了一個String類型的值,對應兩幅圖的路徑。

接下來爲TreeView添加三個事件,Mouse_Down事件、Item_Drag事件和Drag_Enter事件。Mouse_Down事件不用多說,Item_Drag事件發生在拖動的瞬間,Drag_Enter事件發生在進入控件邊緣的瞬間。然後爲PixtureBox添加Drag_Enter事件和Drag_Drop事件,Drag_Drop事件發生在拖動結束時。先上代碼:

<span style="font-size:18px;">private void treeView1_MouseDown(object sender, MouseEventArgs e)
        {
            TreeNode node = treeView1.GetNodeAt(e.X, e.Y);
            if (node != null)
            {
                treeView1.SelectedNode = node;
            }
        }</span>
<span style="font-size:18px;">private void treeView1_ItemDrag(object sender, ItemDragEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                TreeNode node = treeView1.SelectedNode;
                if (node != null)
                {
                    string path = (node.Tag as string);
                    DoDragDrop(path, DragDropEffects.All);
                }
            }
        }</span>
<span style="font-size:18px;"> private void treeView1_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(typeof(string)) == true)
            {
                e.Effect = DragDropEffects.All;
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }
        }</span>
<span style="font-size:18px;">private void pictureBox1_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(typeof(string)) == true)
            {
                e.Effect = DragDropEffects.All;
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }
        }</span>
<span style="font-size:18px;">private void pictureBox1_DragDrop(object sender, DragEventArgs e)
        {
            string imagePath = (string)(e.Data.GetData(typeof(string)));
            if (imagePath != null)
            {
                Image showImage = Image.FromFile(imagePath);
                pictureBox1.Image = showImage;
                Invalidate();
            }
        }</span>


其中,TreeView的Mouse_Down事件是爲了獲取選中的目標節點,用到了TreeView的GetNodeAt函數,該函數出入兩個座標參數,返回該座標位置的節點。Item_Drag事件調用DoDragDrop方法,開始拖放操作。該方法的聲明如下圖(參考MSDN):


其中,data爲要拖動的數據,allowedEffects爲DragDropEffects類型的枚舉的值,它表示在拖放操作期間執行的最終效果。DragDropEffects類型的枚舉成員如下圖:



在Drag_Enter事件中,有用到GetDataPresent函數,該函數確定是否具有指定格式的數據,或者數據是否可以轉換爲指定格式。MSDN上的重載列表如下圖所示:



之後在PictureBox中分別實現了Drag_Enter和Drag_Drop事件,在Drag_Drop事件中,獲取拖動的數據,即圖像的路徑,然後使用Image類的FromFile函數,構造新的Image對象,並將該對象賦值給PictureBox的Image屬性,並刷新,拖動節點1和節點2的效果圖如下:





之前沒有給TreeView添加Mouse_Down事件,直接在Item_Drag事件中使用TreeView.SelectedNode()方法,結果返回的node總是根節點(第一個節點);網上查找資料,有人說是因爲要給每一個node的value屬性設置 不一樣的值,但是在VS2013中我並沒有發現這一屬性。之後又以爲是因爲我將節點的加載代碼寫在Form_Load中的原因,於是有把代碼挪到一個Button的事件相應中,發現問題仍然沒有解決。後邊再研究了一下,原來是selectedNode的默認是TreeView中的第一個節點,所以每一此使用selectedNode之前,需要先改變它,否則就智能得到上一次修改的值或者是默認值。






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章