1
votes

I am using a WPF treeview, when i click on a node\item once it gets selected. When the user clicks on the selected node the second time i want this node\item to get deselected i.e. i should be able to get the event. IsSelected is not called if i click on the selected node\item that is already selected. How do i get it to work?

<TreeView Grid.Column="0" Grid.Row="1" ItemsSource="{Binding source}" Name="mytreeview">
        <TreeView.ItemContainerStyle>
            <Style TargetType="{x:Type TreeViewItem}">
                <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
                <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
                <Setter Property="FontWeight" Value="Normal" />
                <Style.Triggers>
                    <Trigger Property="IsSelected" Value="True">
                        <Setter Property="FontWeight" Value="Bold" />
                    </Trigger>
                </Style.Triggers>
            </Style>
        </TreeView.ItemContainerStyle>
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate ItemsSource="{Binding Children}">
                <TextBlock Text="{Binding displaytext}"/>
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
    </TreeView>

and in my view model i have

 public bool IsSelected
    {
        get 
        { 
            return _isSelected; 
        }
        set
        {
            if (value != _isSelected)
            {
                _isSelected = value;
                if (_isSelected)
                {
                  //my logic
                }

                this.OnPropertyChanged("IsSelected");
            }
        }
    }
3

3 Answers

0
votes
if (value != _isSelected)

Assuming that the UI is even trying to set something, that line is blocking your toggle logic. Something like this should fix at least that part.

    set
    {
        if (value != _isSelected)
        {
            _isSelected = value;
            this.OnPropertyChanged("IsSelected");
        }
        else if(_isSelected)
        {
            IsSelected = false;
        }
    }

Otherwise the UI is checking the selection before setting the value and you'll need to handle it through some other user interaction like handling deselection on click.

0
votes

I know this is a bit late but I've recently had the same requirement (i.e. unselecting a selected TreeViewItem on the second click) and I solved it by declaring an event handler for the 'MouseLeftButtonUp' event in a 'Style' entry for the ItemContainerStyle of the TreeView as follows:

<TreeView.ItemContainerStyle>
    <Style TargetType="{x:Type TreeViewItem}">
        <EventSetter Event="MouseLeftButtonUp" Handler="TreeViewItem_MouseLeftButtonUp"/>
    </Style>
</TreeView.ItemContainerStyle>

The event handler in the code behind was as follows:

private TreeViewItem prevTVI;

private void TreeViewItem_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    TreeViewItem tvi = (TreeViewItem)sender;
    if (tvi == this.prevTVI)
    {
        this.prevTVI = null;
        if (tvi.IsSelected)
            tvi.IsSelected = false;
    }
    else
        this.prevTVI = tvi;
    e.Handled = true;
}

Now, I would like to ask if anyone thinks this approach breaks the MVVM pattern? I personally don't think so as the event handler is only concerned with the View and its objects not anything else but I would like to hear what others have to say, especially if someone has an alternative.

-1
votes

The IsSelected property is only changed when you select a new item. Clicking on the same item twice will normally have no effect. You would need to register the MouseDown event on the TreeView, and then force the item to be deselected in the code-behind.