Необходимо снять выделение с TreeView при удалении элемента. По умолчанию выделяется первый элемент, а задать SelectedItem = null не получается так как это свойство только для чтения. Как это реализовать?
Ответ
В обычном случае вы не создаёте элементы TreeView вручную, а генерируете их автоматически, используя ItemsSource + ItemTemplate
При этом treeView.SelectedItem будет не TreeViewItem, а элемент коллекции, привязанной к ItemsSource. Так что приведение к типу TreeViewItem не сработает.
Чтобы получить из этого собственно визуальный элемент, обычно применяется конструкция list.ItemContainerGenerator.ContainerFromItem(selectedItem);. Но в случае TreeView она, к сожалению, работает лишь на верхнем уровне: каждый TreeViewItem рекурсивно сам является TreeView, и заботится сам о своих контейнерах, так что list.ItemContainerGenerator ничего не знает о вложенных частях дерева.
Неплохое универсально работающее (но многословное) решение — следить за изменением выделенного элемента, и запоминать его в code behind.
Пример:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new[]
{
new DataHolder("Привет-привет", null),
new DataHolder("Пока-пока", null),
new DataHolder(null,
new[]
{
new DataHolder("Я очень", null),
new DataHolder("буду ждать",
new[]
{
new DataHolder("звонка", null)
}),
}),
};
TreeViewItem selectedItemTV = null;
TV.AddHandler(TreeViewItem.SelectedEvent, (RoutedEventHandler)((sender, args) =>
selectedItemTV = (TreeViewItem)args.OriginalSource));
TreeViewItem selectedItemTV2 = null;
TV2.AddHandler(TreeViewItem.SelectedEvent, (RoutedEventHandler)((sender, args) =>
selectedItemTV2 = (TreeViewItem)args.OriginalSource));
var dt = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(5) };
dt.Tick += (sender, args) =>
{
if (selectedItemTV != null)
{
selectedItemTV.IsSelected = false;
selectedItemTV = null;
}
if (selectedItemTV2 != null)
{
selectedItemTV2.IsSelected = false;
selectedItemTV2 = null;
}
};
dt.Start();
}
}
public class DataHolder
{
public string Key { get; private set; }
public IEnumerable
public DataHolder(string key, IEnumerable
Ну или вы можете подписаться обычным способом в XAML'е: TreeViewItem.Selected="TVItemSelected"
Ещё есть решение с полным рекурсивным обходном дерева, и поиском TreeViewItem'а, как описано здесь. Но оно мне кажется слишком уж неэффективным, и наверняка плохо дружит с виртуализацией.
Комментариев нет:
Отправить комментарий