WPF TreeView arrastrar y ordenar disposición de arrastrar y soltar

Un ejemplo de demostración se adjunta en la parte inferior. Los amigos que lo necesiten pueden descargarlo como referencia.

1. Icono

Por alguna razón, el GIF siempre se ve muy atascado, pero en realidad es muy suave.

Debido a problemas de grabación, la animación GIF solo se reproducirá una vez. Si necesita verla repetidamente, cierre la página web y vuelva a abrirla para verla.

 

Hay muy poca información sobre WPF, y no hay nada para encontrar algunas animaciones. Recientemente, necesito usar Treeview para arrastrar y ordenar mi trabajo. Sin embargo, casi no hay ejemplos de demostración relacionados en Internet, por lo que solo puedo jugar solo. En el proceso, también aprendí algunos conocimientos.

2. Principio

Uso la traducción del control para lograr el efecto de arrastre. Al desplazarse hacia el límite, activará el desplazamiento hacia arriba y hacia abajo de TreeView (también se desplazará al desplazarse); si sale del límite, dejará de desplazarse; cuando se desplace hacia arriba y hacia abajo, dejará de desplazarse; cuando se levante el dedo, capture la posición actual del mouse, inserte el elemento arrastrado frente al elemento en la posición actual del mouse, elimine los datos antiguos del conjunto de datos y agregue nuevos datos a la posición agregada

Puntos técnicos:

1. Desplazamiento del control de código TreeView

2. Control de arrastre, desplazamiento

3. Obtenga la posición relativa del control en otros controles principales

4. Use eventos del mouse para desplazarse y ordenar después de arrastrar

3. Análisis de código

Primero, escribimos el diseño, que es un TreeView ordinario. Sin embargo, necesitamos agregar un evento MouseMove al control, que se usa para determinar si el mouse se ha movido al límite y luego realizar la acción de desplazamiento automático correspondiente.

<Window x:Class="WpfAppTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfAppTest"
        mc:Ignorable="d"
        Loaded="OnViewLoaded"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <TreeView x:Name="mTreeView" Width="300" HorizontalAlignment="Left" MouseMove="ParentMove"/>
    </Grid>
</Window>

Luego, durante la inicialización, agregamos los datos de TreeView al Diccionario y luego inicializamos el Elemento de TreeView de acuerdo con los datos del Diccionario.

private void initData()
{
	datas["A"] = new List<string>();
	datas["A"].Add("阿轲");
	datas["A"].Add("艾琳");
	datas["A"].Add("安其拉");

	datas["B"] = new List<string>();
	datas["B"].Add("白起");
	datas["B"].Add("百里守约");
	datas["B"].Add("扁鹊");
	datas["B"].Add("百里玄策");
	datas["B"].Add("不知火舞");

	datas["C"] = new List<string>();
	datas["C"].Add("蔡文姬");
	datas["C"].Add("曹操");
	datas["C"].Add("陈咬金");
	datas["C"].Add("嫦娥");
	datas["C"].Add("成吉思汗");

	datas["D"] = new List<string>();
	datas["D"].Add("狄仁杰");
	datas["D"].Add("典韦");
	datas["D"].Add("貂蝉");
	datas["D"].Add("盾山");
	datas["D"].Add("东皇太一");
	datas["D"].Add("妲己");
	datas["D"].Add("大乔");
	datas["D"].Add("达摩");

	datas["G"] = new List<string>();
	datas["G"].Add("宫本武藏");
	datas["G"].Add("高渐离");
	datas["G"].Add("鬼谷子");
	datas["G"].Add("干将莫邪");
	datas["G"].Add("关羽");
	datas["G"].Add("公孙离");

	datas["H"] = new List<string>();
	datas["H"].Add("后裔");
	datas["H"].Add("韩信");
	datas["H"].Add("花木兰");
	datas["H"].Add("黄忠");
}

private void initViews()
{
	foreach (KeyValuePair<string, List<string>> kv in datas)
	{
		TreeViewItem parentItem = new TreeViewItem();
		parentItem.Header = kv.Key;
		parentItem.Tag = kv.Value;
		mTreeView.Items.Add(parentItem);
		foreach (string info in kv.Value)
			parentItem.Items.Add(creatItem(info));
	}
}

private TreeViewItem creatItem(object header)
{
	TreeViewItem newItem = new TreeViewItem();
	newItem.Header = header;
	newItem.PreviewMouseDown += ItemMouseDown;
	newItem.PreviewMouseMove += ItemMove;
	newItem.PreviewMouseUp += ItemMouseUp;
	newItem.Height = 30;
	return newItem;
}

Una vez que la vista y los datos están listos, comencé a prepararme para la acción de arrastrar. Agregué 3 eventos al elemento anterior, a saber, PreviewMouseDown, PreviewMouseMove y PreviewMouseUp. Estos 3 eventos son la clave para nuestro elemento de arrastre

PreviewMouseDown: Obtenga la posición del clic del mouse como la posición inicial del movimiento. Inicializar la transformación del objeto de traducción

PreviewMouseMove: desplaza el elemento de acuerdo con el movimiento del mouse

PreviewMouseUp: capture el elemento que se insertará cuando se levante el mouse e inserte el elemento

¿No agregamos también el evento MouseMove de TreeView arriba? Este evento es principalmente para la detección de bordes, y el desplazamiento automático también estará habilitado aquí.

El código del evento PreviewMouseDown es relativamente sencillo, lastPosition registra las coordenadas del último movimiento, que se utiliza para calcular cuánto se ha movido el ratón, y cuánto movemos el Item. _isMouseDown es la marca de arrastre, solo cuando se presiona, se calculará la distancia de movimiento del mouse y transform es el objeto que usamos para arrastrar el elemento

private void ItemMouseDown(object sender, MouseButtonEventArgs e)
{
	lastPosition = 0;
	var c = sender as UIElement;
	_isMouseDown = true;
	TreeViewItem treeViewItem = (TreeViewItem)sender;
	mouseDownOffset = e.GetPosition(treeViewItem).Y + 5;
	_mouseDownPosition = e.GetPosition(this);
	var transform = c.RenderTransform as TranslateTransform;
	if (transform == null)
	{
		transform = new TranslateTransform();
		c.RenderTransform = transform;
	}
	c.CaptureMouse();
}

El evento PreviewMouseMove calcula la distancia que se mueve el mouse y luego arrastra el elemento la distancia correspondiente. Luego proporcione la posición actual del eje Y a lastPosition para el siguiente cálculo.

e.GetPosition(UIElement) es para obtener la posición del mouse en el control.Para obtener la posición relativa de qué control, pase el control como parámetro a GetPosition para obtener la posición. Se pueden realizar sumas y restas entre Posición y Posición para calcular la distancia en línea recta entre dos coordenadas

if (_isMouseDown && !isRollingItem[0])
{
	TreeViewItem viewItem = (TreeViewItem)sender;
	dragingItemHeight = viewItem.ActualHeight;
	var c = sender as UIElement;
	var pos = e.GetPosition(this);
	var dp = pos - _mouseDownPosition;
	transform = c.RenderTransform as TranslateTransform;
	//transform.X = _mouseDownControlPosition.X + dp.X;
	//transform.Y = _mouseDownControlPosition.Y + dp.Y;
	transform.Y = transform.Y + (dp.Y - lastPosition);
	lastPosition = dp.Y;
}

El evento PreviewMouseUp calcula directamente la posición actual e inserta el elemento arrastrado en la posición actual.

Cuando uso el control en el proyecto, descubrí que arrastrar hacia arriba estará encima de otros Elementos, y arrastrar hacia abajo estará debajo del Elemento (ocluido). Por supuesto, mi artículo es mi diseño personalizado. Cuando aparece el mouse, no puede capturar en qué elemento permanece el mouse a tiempo, y debe esperar alrededor de 100 milisegundos para obtenerlo. Entonces, si encuentra un problema, debe solucionarlo.

Veamos el código de desplazamiento automático de TreeView. Esto es más importante. Mientras TreeView se desplaza, el elemento arrastrado también debe traducirse.

private void ScrollingOnMainThread(object obj)
{
	bool isDownScroll = (bool)obj;
	if (isDownScroll)
	{
		if (scrollViewer.VerticalOffset >= (scrollViewer.ExtentHeight - mTreeView.ActualHeight)) return;
		scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset + 6);    //向下调节垂直滚动条的位置;
		transform.Y += 6;
	}
	else
	{
		if (scrollViewer.VerticalOffset <= 0) return;
		scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - 6);    //向上调节垂直滚动条的位置;
		transform.Y -= 6;
	}
}

Eso es todo lo que importa, ahora sus controles también deberían poder moverse.

Si aún necesita una referencia de ejemplo de demostración o verifique el efecto. Por favor vea el enlace

WPFTreeView Arrastrar Ordenar Arreglo de arrastrar y soltar-Recursos de documentación del sistema de escritorio-Descarga de CSDN

El código de este artículo es fácil de implementar y tiene una gran escalabilidad. El ejemplo de demostración tiene un total de 267 líneas. El código también incluye códigos no lógicos, como la inicialización de datos y la inicialización del control de vista. El código es fácil de mantener. 

Si no entiende algo durante el uso, también puede preguntar a través de mensajes privados. A menudo estoy en línea para ayudarlo a responder sus dificultades durante el uso. El ejemplo de demostración puede no ser perfecto. Si encuentra un problema, puede mencionarlo para que todos aprendan juntos y mejoren el proyecto. Este artículo prueba el código que he creado a mano. Si le gusta, por favor déle me gusta y apóyelo.

Supongo que te gusta

Origin blog.csdn.net/baoolong/article/details/128302036
Recomendado
Clasificación