How to change VisualState UserControl used as ItemTemplate in ListView

I have a UserControl with certain VisualStates:

<UserControl>
  <Grid Height="50" HorizontalAlignment="Stretch">
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="SelectionStates">
            <VisualState x:Name="Unselected"/>
            <VisualState x:Name="Selected">
            <!-- more code -->

      

and I am using it as the ItemTemplate of my ListView. When an item is selected from the ListView, I also want to change the VisualState in the DataTemplate. At the moment I have a method like this:

private void list_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
  ListView listView = sender as ListView;
  foreach (var item in e.AddedItems)
    VisualStateManager.GoToState((listView.ContainerFromItem(item) as ListViewItem).ContentTemplateRoot as myControl, "Selected", false);
 }

      

This seems to work, but (listView.ContainerFromItem(item) as ListViewItem

is null in some cases and therefore an exception is thrown.

Is there any other / better way to change the VisualState of the DataTemplate being used?

+3


source to share


1 answer


The reason the item container is (i.e. ListViewItem

) equal null

is because the ListView

default ItemsStackPanel

pane is a pixel-based pane-based pane that only displays items when they are in or near the current viewport.

Because you set up the selected items in code, these items might not appear, their containers are returned as null

.

One simple solution would be to replace ItemsStackPanel

with normal StackPanel

, however this would break the built-in virtualization.

Here's another solution without changing the panel.



First your existing code is still needed, you just need to do a null check if the element container is null, just do nothing.

Then you need to subscribe to the event ListView

ContainerContentChanging

. This is triggered when loading the container. So basically, you are checking if the item that is loaded here is one of the selected items. If so, change its visual state. Something like that -

private void MyListView_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args)
{
    if (this.MyListView.SelectedItems.Contains(args.Item))
    {
        // get the container
        var container = (ListViewItem)args.ItemContainer; 

        // do your visual state change here, when the container was previously null
    }
}

      

+2


source







All Articles