Обычно вы не создадите DataTemplate, содержащий TreeViewItem, потому что инфраструктура привязки будет создавать TreeViewItem для вас - все, что вам нужно сделать, это указать, что должно отображаться как content TreeViewItem. Вот почему в найденных вами примерах используются TextBlocks вместо TreeViewItems в DataTemplate.
Я подозреваю, что использование TreeViewItem вместо TextBlock приводит к чрезмерному отступу, потому что у вас есть (вручную созданный) TreeViewItem в вашем DataTemplate (который имеет один уровень отступа) внутри другого (автоматического) TreeViewItem (который имеет другой уровень отступа) , Следовательно, использование TextBlock вместо TreeViewItem должно вылечить это. Интеграция ContextMenu не должна быть проблемой, потому что TextBlock также имеет свойство ContextMenu.
Таким образом, вы можете просто изменить свой DataTemplate следующим образом:
<DataTemplate x:Key="RoomTemplate">
<TextBlock Text="{Binding Name}">
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem Header="Open" />
<MenuItem Header="Remove" />
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
Между прочим, для TreeViews обычно используется HierarchicalDataTemplate, а не обычный DataTemplate, потому что это позволяет использовать несколько уровней элементов через свойство HierarchicalDataTemplate.ItemsSource. Это может не потребоваться в вашем сценарии, хотя.