Вдохновленный ответом Феанора, я попытался сделать TreeViewItem
легкодоступным для каждого элемента данных, для которого был создан TreeViewItem
.
Идея состоит в том, чтобы добавить поле типа TreeViewItem
в модель представления, также предоставляемую через интерфейс, и сделать так, чтобы TreeView
автоматически заполняло его при создании контейнера TreeViewItem
.
Это делается путем создания подкласса TreeView
и присоединения события к ItemContainerGenerator
, который записывает TreeViewItem
при каждом его создании. К ошибкам можно отнести тот факт, что TreeViewItem
создаются лениво, поэтому в определенные моменты времени они могут быть действительно недоступны.
С момента публикации этого ответа я продолжил развивать его и долгое время использовал его в одном проекте. Пока никаких проблем, кроме того факта, что это нарушает MVVM (но также экономит тонну шаблонов для простых случаев). Источник здесь .
Использование
Выберите родительский элемент для выбранного элемента и сверните его, убедившись, что он находится в представлении:
...
var selected = myTreeView.SelectedItem as MyItem;
selected.Parent.TreeViewItem.IsSelected = true;
selected.Parent.TreeViewItem.IsExpanded = false;
selected.Parent.TreeViewItem.BringIntoView();
...
Объявления:
<Window ...
xmlns:tvi="clr-namespace:TreeViewItems"
...>
...
<tvi:TreeViewWithItem x:Name="myTreeView">
<HierarchicalDataTemplate DataType = "{x:Type src:MyItem}"
ItemsSource = "{Binding Children}">
<TextBlock Text="{Binding Path=Name}"/>
</HierarchicalDataTemplate>
</tvi:TreeViewWithItem>
...
</Window>
class MyItem : IHasTreeViewItem
{
public string Name { get; set; }
public ObservableCollection<MyItem> Children { get; set; }
public MyItem Parent;
public TreeViewItem TreeViewItem { get; set; }
...
}
Код
public class TreeViewWithItem : TreeView
{
public TreeViewWithItem()
{
ItemContainerGenerator.StatusChanged += ItemContainerGenerator_StatusChanged;
}
private void ItemContainerGenerator_StatusChanged(object sender, EventArgs e)
{
var generator = sender as ItemContainerGenerator;
if (generator.Status == GeneratorStatus.ContainersGenerated)
{
int i = 0;
while (true)
{
var container = generator.ContainerFromIndex(i);
if (container == null)
break;
var tvi = container as TreeViewItem;
if (tvi != null)
tvi.ItemContainerGenerator.StatusChanged += ItemContainerGenerator_StatusChanged;
var item = generator.ItemFromContainer(container) as IHasTreeViewItem;
if (item != null)
item.TreeViewItem = tvi;
i++;
}
}
}
}
interface IHasTreeViewItem
{
TreeViewItem TreeViewItem { get; set; }
}