Ваш вопрос немного сбивает с толку. Но похоже, что вы пытаетесь получить элемент данных TreeViewItem
, который является целью перетаскивания операции перетаскивания.
Это довольно просто. Все, что вам нужно знать, это то, что если контейнер элемента генерируется автоматически с помощью привязки данных (ItemsControl.ItemsSource
), DataContext
контейнера является самим элементом данных.
Это относится ко всем контейнерам элементов ItemsControl
(например, ComboBoxItem
, ListBoxItem
, ListViewItem
).
Итак, TreeViewItem.DataContext
ссылается на базовый TreeItem
экземпляр, который обернут TreeViewItem
:
private void TreeViewItem_Drop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent("DragableTreeViewItem"))
{
var sourceItem = e.Data.GetData("DragableTreeViewItem") as TreeItem;
var dropTargetItemContainer = sender as TreeViewItem;
var dropTargetItem = targetItemContainer.DataContext as TreeItem;
}
}
Замечание
Похоже, вы используете ItemContainerGenerator
неправильно. TreeView.ItemContainerGenerator
будет обрабатывать только элементы верхнего уровня (то есть дочерние элементы). Но так как у узла дерева могут быть дочерние узлы, каждый TreeViewItem
сам по себе является ItemsControl
, поскольку он содержит ItemsPresenter
для отображения дочерних элементов.
Поэтому вы должны использовать соответствующий ItemContainerGenerator
для извлечения дочернего контейнера или ItemContainerGenerator
вернет null
.
Для элементов верхнего уровня используйте TreeView.ItemContainerGenerator
.
Для дочерних элементов используйте родительский TreeViewItem.ItemContainerGenerator
.
Кроме того, в случае Виртуализация пользовательского интерфейса включена, не все контейнеры генерируются при загрузке TreeView
. Они генерируются при необходимости, например, для отображения. Эти контейнеры (TreeViewItem
) также используются совместно для экономии ресурсов. Поэтому, как только вы установите свойство TreeViewItem.Tag
, его значение может быть потеряно, так как новый экземпляр TreeViewItem
будет сгенерирован позже для переноса элемента данных.
Итак, вы начинаете с узла root и получаете его сгенерированный контейнер. , Теперь выполните поиск по дереву, пройдя по TreeViewItems
с использованием заданного алгоритма c, пока не найдете узел, где DataContext
равен элементу данных, который вы ищете, и, например, измените свойство Tag
.
You получить доступ к дочерним элементам, например, treeViewItemA
, ссылаясь на свойство treeViewItemA.Items
, и получить их контейнеры, вызвав метод treeVieItemA.ItemContainerGenerator.ContainerFromItem
для каждого дочернего элемента:
Пример
public static class MyExtensions
{
// Get item container of item from TreeView, TreeViewItem, ListView or any ItemsControl
public static bool TryGetContainerOfChildItem<TItemContainer>(this ItemsControl itemsControl, object item, out TItemContainer itemContainer) where TItemContainer : DependencyObject
{
itemContainer = null;
foreach (object childItem in itemsControl.Items)
{
if (childItem == item)
{
itemContainer = (TItemContainer) itemsControl.ItemContainerGenerator.ContainerFromItem(item);
return true;
}
DependencyObject childItemContainer = itemsControl.ItemContainerGenerator.ContainerFromItem(childItem);
if (childItemContainer is ItemsControl childItemsControl && childItemsControl.TryGetContainerOfChildItem(item, out itemContainer))
{
return true;
}
}
return false;
}
}
Использование
// Search whole TreeView
if (treeView.TryGetContainerOfChildItem(item, out TreeViewItem itemContainer)
{
...
}
// Search from a specific parent TreeViewItem node
if (treeViewItem.TryGetContainerOfChildItem(item, out TreeViewItem itemContainer)
{
...
}