8

Is there a nice way (except retemplating the whole TreeViewItem.Template) to disable selection in TreeView?

I am basically looking for the ItemsControl style of the TreeView (An ItemsControl is the best use to 'disable' selection on ListBox, read this post)

Community
  • 1
  • 1
Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632
  • Here is another approach: http://stackoverflow.com/questions/1398559/there-aint-listbox-selectionmode-none-is-there-another-way-to-disable-selecti/1398625#1398625/1228 –  Apr 26 '11 at 12:19

8 Answers8

22

Try this:

<Trigger Property="HasItems" Value="true">
   <Setter Property="Focusable" Value="false" />
</Trigger>
Morten Strand
  • 225
  • 2
  • 5
6

This did the trick for me (based on this answer, but no tied to item - selection is disabled whatsoever):

<TreeView>
  <TreeView.ItemContainerStyle>
    <Style TargetType="TreeViewItem">
      <Setter Property="Focusable" Value="False" />
    </Style>
  </TreeView.ItemContainerStyle>
</TreeView>
Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632
5

Based off of the links to the currently accepted answer, I implemented this in my project:

<ListView.ItemContainerStyle>
    <Style TargetType="{x:Type ListViewItem}">
        <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
    </Style>
</ListView.ItemContainerStyle>

Works for TreeViewItem as well. And in the view model:

protected bool _DisableSelection;
private bool _IsSelected;
public bool IsSelected
{
    get { return _IsSelected; }
    set
    {
        if (value == _IsSelected) return;
        _IsSelected = _DisableSelection ? false : value;
        NotifyPropertyChanged();
    }
}

Now you don't have to go hunting!

Balki
  • 121
  • 1
  • 3
1

I just unselected the TreeViewItems as they get selected. I use TreeView only once. However if I added it in several places I would consider looking in to adding this to a Attached Behavior.

Xaml:

<TreeView SelectedItemChanged="TreeView_SelectionChanged">

Code behind:

private void TreeView_SelectionChanged(object sender, RoutedEventArgs e)
{
    if (!(sender is TreeView myTreeView)) return;
    var selectedItem = (TreeViewItem)myTreeView.SelectedItem;
    if (selectedItem == null) return;
    selectedItem.IsSelected = false;
}
g t
  • 7,287
  • 7
  • 50
  • 85
1

I decided to write a reusable behavior, HTH:

Namespace Components
  Public NotInheritable Class TreeViewBehavior

    Public Shared Function GetIsTransparent(
      ByVal element As TreeViewItem) As Boolean
      If element Is Nothing Then Throw New ArgumentNullException("element")
      Return element.GetValue(IsTransparentProperty)
    End Function
    Public Shared Sub SetIsTransparent(ByVal element As TreeViewItem,
                                       ByVal value As Boolean)
      If element Is Nothing Then Throw New ArgumentNullException("element")
      element.SetValue(IsTransparentProperty, value)
    End Sub
    Public Shared ReadOnly IsTransparentProperty As DependencyProperty =
      DependencyProperty.RegisterAttached("IsTransparent", GetType(Boolean),
        GetType(TreeViewBehavior),
        New FrameworkPropertyMetadata(False,
          AddressOf IsTransparent_PropertyChanged))
    Private Shared Sub IsTransparent_PropertyChanged(
      ByVal sender As Object, ByVal e As DependencyPropertyChangedEventArgs)
      Dim tvi = DirectCast(sender, TreeViewItem)
      Dim isTransparent = CBool(e.NewValue)

      If isTransparent Then
        AddHandler tvi.Selected, AddressOf tvi_Selected
      Else
        RemoveHandler tvi.Selected, AddressOf tvi_Selected
      End If
    End Sub
    Private Shared Sub tvi_Selected(ByVal sender As Object,
                                    ByVal e As RoutedEventArgs)
      Dim treeViewItem = DirectCast(sender, TreeViewItem)
      If Not treeViewItem.IsSelected Then Exit Sub

      treeViewItem.Dispatcher.Invoke(
        Sub(tvi As TreeViewItem) tvi.IsSelected = False,
        System.Windows.Threading.DispatcherPriority.Send,
        treeViewItem)
    End Sub

  End Class
End Namespace

Usage:

<Window xmlns:components="clr-namespace:WpfApplication.Components">
  <TreeView>
    <TreeView.ItemContainerStyle>
      <Style TargetType="TreeViewItem">
        <Setter 
          Property="components:TreeViewBehavior.IsTransparent" 
          Value="True" />
      </Style>
    </TreeView.ItemContainerStyle>
  </TreeView>
</Window> 
Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632
1

Whenever an item is selected, you could "unselect" it. Ex. modify the code from http://www.codeproject.com/KB/WPF/TreeView_SelectionWPF.aspx or use a MVVM approach (see http://www.codeproject.com/KB/WPF/TreeViewWithViewModel.aspx) and always set IsSelected back to false.

Daniel Rose
  • 17,233
  • 9
  • 65
  • 88
  • 7
    Whilst this may theoretically answer the question, we would like you to include the essential parts of the linked article in your answer, and provide the [link for reference](http://meta.stackexchange.com/q/8259). Failing to do that leaves the answer at risk from link rot. – Kev Oct 30 '12 at 23:45
1

I tried this and it worked for me. Because I have a simple and not dynamic treeview. But I think it can work by putting it in a style

<TreeViewItem ... Focusable="False" IsSelected="False"/>
CongoTM
  • 21
  • 3
  • 6
    While this code snippet may be the solution, [including an explanation](//meta.stackexchange.com/questions/114762/explaining-entirely-‌​code-based-answers) really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. – Neo Anderson Sep 18 '20 at 19:35
  • Thanks @NeoAnderson. I'm new here, but I just want to help. – CongoTM Sep 21 '20 at 10:12
  • We all want to help. The goal is to do it as efficient as we can. Thanks for explaining the code snippet. – Neo Anderson Sep 21 '20 at 10:58
0

I did this a differently than the accepted answer:

Lets say that you have a property in your ViewModel (say 'ShouldPreventSelection') Now when ShouldPreventSelection is true you want selection to be disabled:

In your TreeView fire the PreviewSelected event like so:

<TreeView Name="TreeView1"
     ...
     PreviewSelected="TreeView1_PreviewSelected"
     ..
/>

Then in the codebehind you can the following:

private void TreeView1_PreviewSelected(object sender, RoutedEventArgs e)
{
    MyViewModel myViewModel = TreeView1.DataContext as MyViewModel;
    if (myViewModel == null)
    {
        return;
    }
    if (myViewModel .ShouldPreventSelection)
    {
        e.Handled = true;
    }

}
Danield
  • 121,619
  • 37
  • 226
  • 255
  • 6
    There doesn't seem to be any `PreviewSelected` event on the WPF `TreeView`. – svick Nov 06 '12 at 17:17
  • hmm I was using Telerik's RadTreeView and I guess that I assumed that the PreviewSelected event was available in a regular TreeView. – Danield Nov 06 '12 at 21:29