#c# #wpf #treeview #contentcontrol
#c# #wpf #просмотр дерева #contentcontrol
Вопрос:
У меня есть просмотр дерева с itemsource, содержащий элементы пользовательского класса TreeViewItem.
У меня есть свойство SelectedTreeviewItemViewModel типа TreeViewItem.
public TreeviewItem SelectedTreeviewItemViewModel //with INPC
У меня есть элемент управления содержимым где-то еще в окне
<ContentControl Content="{Binding SelectedTreeviewItemViewModel}" />
с таблицей данных следующим образом:
<DataTemplate DataType="{x:Type TreeviewItem}">
<uc:TreeviewCustomView />
</DataTemplate>
Когда я нажимаю на элемент treeview, запускается событие SelectedItemChanged, и я устанавливаю SelectedTreeviewItemViewModel, которое заставляет contentcontrol обновлять его содержимое.
Логика в порядке, однако я заметил, что когда я нажимаю на новый элемент в treeview, некоторые данные обновляются, но я не перехожу в конструктор пользовательского элемента управления (uc: TreeviewCustomView).
Задействована ли какая-то виртуализация? Я предполагаю, что WPF кэширует datatemplate; могу ли я каким-либо образом заставить WPF воссоздавать пользовательский элемент управления с нуля (таким образом, переходя в конструктор) каждый раз, когда я нажимаю на элемент treeview?
Ответ №1:
Древовидные представления виртуализируются по умолчанию при использовании привязки. Если вы переключите режим на VirtualizingPanel.VirtualizationMode=»Standard», вместо «Recycling» должен быть вызван конструктор.
Комментарии:
1. Проблема не находится в treeview. Я могу использовать режим виртуализации, но это не принесет мне никакой пользы: проблема находится в элементе управления контентом, который, похоже, кэширует храм данных.
Ответ №2:
Вот что помогло мне:
Я создаю селектор шаблонов, который в основном оборачивает шаблон в другой шаблон, заставляя создавать новый экземпляр. Пожалуйста, имейте в виду, что это может привести к серьезным проблемам с производительностью!
В моем xaml я начинаю с присвоения имени шаблону данных:
<DataTemplate x:Key="TreeviewItemTemplate" DataType="{x:Type TreeviewItem}">
<uc:TreeviewCustomView />
</DataTemplate>
Затем я создаю селектор шаблонов следующим образом:
public class TreeviewItemTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item == null)
{
return null;
}
var declaredDataTemplate = ((FrameworkElement)container).FindResource("TreeviewItemTemplate") as DataTemplate;
var wrappedDataTemplate = WrapDataTemplate(declaredDataTemplate );
return wrappedDataTemplate;
}
private static DataTemplate WrapDataTemplate(DataTemplate declaredDataTemplate)
{
var frameworkElementFactory = new FrameworkElementFactory(typeof(ContentPresenter));
frameworkElementFactory.SetValue(ContentPresenter.ContentTemplateProperty, declaredDataTemplate);
var dataTemplate = new DataTemplate();
dataTemplate.VisualTree = frameworkElementFactory;
return dataTemplate;
}
}
И, наконец, я использую селектор в своем элементе управления контентом:
<ContentControl Content="{Binding SelectedTreeviewItemViewModel }"
ContentTemplateSelector="{StaticResource TreeviewItemTemplateSelector }" />