[UWP][XAML] How to disable and skip items in a ListView but show them as regular items

Are you looking for a way to show a UWP ListView where certain items cannot be clicked, cannot be selected and do not get focused while using arrow keys up and down? This tutorial shows you how to use a ListView base class and minimal styling to get that effect.

Stop, dave

In the next animation, all items with the name dave have been disabled and are not selectable. Here is what it looks like:

deselectable items in a listview

ListViewItems have an IsEnabled property and are meant to disable equally items in a list. Our goal here is to have To get this behavior we will create the following:

IIsEnabled

Let’s assume we are using ViewModels for each name in the list. We need a way to add a property to the ViewModel that returns if an item is enabled.

Create interface IIsEnabled for this:

public interface IIsEnabled
{
    bool IsEnabled { get; }
}

Implement IIsEnabled in PersonViewModel. As you see we will set all items with name Dave to disabled.

public class PersonViewModel : IIsEnabled
{
    public string Name { get; set; }
    public bool IsEnabled => Name != "Dave";
}

Override PrepareContainerForItemOverride

Create a base class ListView2 and inherit from ListView. The PrepareContainerForItemOverride is executed for all rendered items. Here we can set properties.

Set IsEnabled to false to prevent selecting. Set IsHitTestVisible to false to prevent clicking on it.

public class ListView2 : ListView
{
    protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
    {
        base.PrepareContainerForItemOverride(element, item);

        if (element is ListViewItem container && item is IIsEnabled binaryItem)
        {
            container.IsEnabled = binaryItem.IsEnabled;
            container.IsHitTestVisible = binaryItem.IsEnabled;
        }
    }
}

To use ListView2 in your XAML, take this code:

<local:ListView2 x:Name="listview">
    <ListView.ItemTemplate>
        <DataTemplate x:DataType="local:PersonViewModel">
            <TextBlock Text="{x:Bind Name}"/>
        </DataTemplate>
    </ListView.ItemTemplate>
</local:ListView2>

Feed it some items in the code behind:

public MainPage()
{
    this.InitializeComponent();
    listview.ItemsSource = new List<PersonViewModel> {
        new PersonViewModel { Name = "Vera" },
        new PersonViewModel { Name = "Chuck" },
        new PersonViewModel { Name = "Dave" },
        new PersonViewModel { Name = "Vera" },
        new PersonViewModel { Name = "Chuck" },
        new PersonViewModel { Name = "Dave" },
        new PersonViewModel { Name = "Vera" },
        new PersonViewModel { Name = "Chuck" },
        new PersonViewModel { Name = "Dave" },
        new PersonViewModel { Name = "Vera" },
        new PersonViewModel { Name = "Chuck" },
        new PersonViewModel { Name = "Dave" },
    };
}

The result looks like this:

opacity in a listview

Notice how all dave-items are greyed out a bit. This is because the ListViewItemPresenter has a DisabledOpacity set to 0.55. You have a few options here. If you already created a ListView ItemContainerStyle, you can set DisabledOpacity to 1. If you want a more lightweight approach, set the ListViewItemDisabledThemeOpacity in the ListView2 resources like this:

<local:ListView2 x:Name="listview">
    <local:ListView2.Resources>
        <x:Double x:Key="ListViewItemDisabledThemeOpacity">1</x:Double>
    </local:ListView2.Resources>
    <ListView.ItemTemplate>
        <DataTemplate x:DataType="local:PersonViewModel">
            <TextBlock Text="{x:Bind Name}"/>
        </DataTemplate>
    </ListView.ItemTemplate>
</local:ListView2>