C# treeview滚动条事件

C# treeview滚动条事件

问题描述

TreeView过长;
不点击节点,鼠标滚轮可以让滚动条滚动;
点击节点,按住不放,拖拽节点到页面外部,页面不会自动滚动,鼠标滚轮也不会让滚动条滚动。

解决思路

在查过官方文档就知道C#的treeview封装了滚动条事件,没有提供相应的api接口,想要重载滚动条的事件是行不通的。

由于只有按住节点的时候才有这个滚动的需求,因此我想了一种“曲线救国”的方法:重载TreeView的拖拽事件。

QueryContinueDrag(object sender, QueryContinueDragEventArgs e)

这个是TreeView的拖拽事件,处于节点拖拽状态下才会触发该事件函数。

如果C#写多了,就会知道TreeView有个节点跳转的功能,类似页面右下角的“返回顶部”的功能,只要把焦点定位和拖拽就可以让页面自动滚动。

(我没实现重载拖拽时的鼠标滚轮,因为节点焦点乱飘不适合我的需求)

代码

事前工作1:向上、向下滚动定时器

/// <summary>
/// 拖拽上滚动定时器
/// </summary>
private Timer ScrollUpDelayTimer = new Timer();

/// <summary>
/// 编辑器拖拽下滚动定时器
/// </summary>
private Timer ScrollDownDelayTimer = new Timer();

public MYTreeView()
{
	InitializeComponent();
	// 初始化拖拽滚动定时器
	// 初始化时间
	ScrollUpDelayTimer.Interval = ScrollDelayTimerMS;
	ScrollDownDelayTimer.Interval = ScrollDelayTimerMS;
	// 初始化事件
	ScrollUpDelayTimer.Tick += new EventHandler(ScrollUpEvent);
	ScrollDownDelayTimer.Tick += new EventHandler(ScrollDownEvent);
}

事前工作2:向上、向下滚动事件

/// <summary>
/// 向上滚
/// </summary>
/// <param name="currentIndex"></param>
private void ScrollUp()
{
    int currentIndex = treeView.SelectedNode.Index;
    if (currentIndex >= 1)
    {
        currentIndex--;
        treeView.SelectedNode = treeView.Nodes[currentIndex];
        treeView.Nodes[currentIndex].EnsureVisible();
    }
}

private void ScrollUpEvent(object sender, EventArgs e)
{
    ScrollUp();
}

/// <summary>
/// 向下滚
/// </summary>
/// <param name="currentIndex"></param>
private void ScrollDown()
{    int currentIndex = treeView.SelectedNode.Index;
    if (currentIndex < treeView.Nodes.Count - 1)
    {
        currentIndex++;
        treeView.SelectedNode = treeView.Nodes[currentIndex];
        treeView.Nodes[currentIndex].EnsureVisible();
        int childIndex = this.treeView.Nodes[currentIndex].Nodes.Count - 1;
        if (childIndex >= 0)
        {
            treeView.Nodes[currentIndex].Nodes[childIndex].EnsureVisible();
        }
    }
}

private void ScrollDownEvent(object sender, EventArgs e)
{
    ScrollDown();
}

准备完成,重载TreeView的拖拽事件

/// <summary>
/// 拖拽改变滚动条位置
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MYTreeView_QueryContinueDrag(object sender, QueryContinueDragEventArgs e)
{
	TreeNode node = treeView.SelectedNode;
	Point currentPoint = treeView.PointToClient(new Point(Control.MousePosition.X, Control.MousePosition.Y));
	while (node.Parent != null)
	{
		node = node.Parent;
	}
	int currentIndex = node.Index;
	if (currentPoint.Y < 0 && currentIndex >= 1)
	{
		ScrollUpDelayTimer.Start();
	}
	else if (currentPoint.Y > treeView.Height && currentIndex < treeView.Nodes.Count - 1)
	{
		ScrollDownDelayTimer.Start();
	}
	else
	{
		ScrollUpDelayTimer.Stop();
		ScrollDownDelayTimer.Stop();
	}
}

为了方便测试,还可以加个快捷键在里面

/// <summary>
/// 拖拽改变滚动条位置
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void FlowEditorTreeView_QueryContinueDrag(object sender, QueryContinueDragEventArgs e)
{
	TreeNode node = treeView.SelectedNode;
	Point currentPoint = treeView.PointToClient(new Point(Control.MousePosition.X, Control.MousePosition.Y));
	while (node.Parent != null)
	{
		node = node.Parent;
	}
	int currentIndex = node.Index;
	// CTRL向上滚, ALT向下滚
	if (e.KeyState == 9 || e.KeyState == 33)
	{

		if (e.KeyState == 9 && currentIndex >= 1)
		{
			ScrollUp();
		}
		else if (e.KeyState == 33 && currentIndex < treeView.Nodes.Count - 1)
		{
			ScrollDown();
		}
	}
	else
	{
		if (currentPoint.Y < 0 && currentIndex >= 1)
		{
			ScrollUpDelayTimer.Start();
		}
		else if (currentPoint.Y > treeView.Height && currentIndex < treeView.Nodes.Count - 1)
		{
			ScrollDownDelayTimer.Start();
		}
		else
		{
			ScrollUpDelayTimer.Stop();
			ScrollDownDelayTimer.Stop();
		}
	}
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值