user1336827
user1336827

Reputation: 1826

CollectionViewSource unselect selectedItem when clicking a group name

I have a listbox that has its itemSource bound to a collectionViewSource that is grouped and has 2 levels of groupings over the actual items:

        <ListBox ItemsSource="{Binding Source={StaticResource myCVS}}" ItemTemplate="{StaticResource myItemsTemplate}" ItemContainerStyle="{StaticResource myItemsStyle}" SelectedItem="{Binding SelectedListItem}" >
            <ListBox.GroupStyle>
                <GroupStyle ContainerStyle="{StaticResource HeaderStyle}" />
                <GroupStyle ContainerStyle="{StaticResource SubHeaderStyle}" />
            </ListBox.GroupStyle>
        </ListBox>

With a CollectionViewSource bound to an ObservabeleCollection:

       <CollectionViewSource x:Key="myCVS" Source="{Binding Path=myItemsToGroup}">
            <CollectionViewSource.GroupDescriptions>
                <PropertyGroupDescription PropertyName="HeaderName" />
                <PropertyGroupDescription PropertyName="SubHeaderName" />
            </CollectionViewSource.GroupDescriptions>
        </CollectionViewSource>

the items in the ObservalbleCollection look like:

public class Items
{
    public string GroupName;
    public string SubGroupName;
    public string ItemName;
}

This all works great i end up with:

Header1
 |_SubHeader1
     |_item1
     |_item2
Header2
 |_SubHeader2
     |_item1
     |_item2

The problem is if i click an item it becomes selected, and stays selected if I click on a header or subheader. If a header is clicked I would like to set the SelectedItem to null. I am using a command to remove the SelectedItem from the UI, but i don't want the command to execute if a header or subheader is being clicked only when a item is being clicked.

Upvotes: 2

Views: 1087

Answers (1)

Kcvin
Kcvin

Reputation: 5163

GroupStyles are not selectable, so of course your view model won't see a selection change happen.

To work around this, you can use some code behind. What you'll notice is if you click on the items in the ListBox, then ListBoxItem will set the MouseUp event's Handled property to true. If you click anywhere else on the ListBox, nothing handles the event. With that being said, you can set your selected item based on the state of Handled.

XAML:

<ListBox ItemsSource="{Binding Source={StaticResource myCVS}}"
         ItemTemplate="{StaticResource myItemsTemplate}"
         ItemContainerStyle="{StaticResource myItemsStyle}"
         SelectedItem="{Binding SelectedListItem}"
         MouseLeftButtonUp="ListBox_MouseLeftButtonUp">

Code-behind:

private void ListBox_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    if(!e.Handled)
    {
        var lb = sender as ListBox;
        lb.SelectedItem = null;
    }
}

Addendum:

Clicking on an already selected item will set the SelectedItem to null. To prevent that, do this: instead of using MouseLeftButtonUp use MouseDown:

<ListBox ItemsSource="{Binding Source={StaticResource myCVS}}"
         SelectedItem="{Binding SelectedListItem}"
         MouseDown="ListBox_MouseLeftButtonUp">

Here is the state of my current application (GroupStyle's) don't get drawn properly, but the implementation is what's important here. If this doesn't do it for you, I would implement a pure MVVM approach.

Upvotes: 2

Related Questions