Hide ListViewItem in WPF ListView

wpf
13,831

Solution 1

Yeah, this is easy.

The first thing you need to do is to add a property to the class you are binding to. For example, if you are binding to a User class with FirstName and LastName, just add a Boolean IsSupposedToShow property (you can use any property you like, of course). Like this:

class User: INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public string FirstName { get; set; }
    public string LastName { get; set; }

    private bool m_IsSupposedToShow;
    public bool IsSupposedToShow
    {
        get { return m_IsSupposedToShow; }
        set
        {
            if (m_IsSupposedToShow == value)
                return;
            m_IsSupposedToShow = value;
            if (PropertyChanged != null)
                PropertyChanged(this, 
                    new PropertyChangedEventArgs("IsSupposedToShow"));
        }
    }
}

Then, remember, to hide some item, don't do it in the UI - no no no! Do it in the data. I mean, look for the User record that you want to hide and change that property in it behind the scenes (like in a View Model) - let the UI react. Make the XAML obey the data.

Like this:

<DataTemplate DataType="{x:Type YourType}">
    <DataTemplate.Resources>
        <Style TargetType="{x:Type TextBlock}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsSupposedToShow}" Value="False">
                    <Setter Property="Visibility" Value="Collapsed"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </DataTemplate.Resources>
    <!-- your UI here -->
    <TextBlock> 
        <TextBlock.Text> 
        <MultiBinding StringFormat="{}{0}, {1}"> 
            <Binding Path="LastName" /> 
            <Binding Path="FirstName" /> 
        </MultiBinding> 
        </TextBlock.Text>
    </TextBlock>
</DataTemplate>

When you change IsSupposedToShow to false, then the XAML understands it is supposed to change the visibility of the whole DataTemplate. It's all wired up for you by WPF and presto, it's what you wanted in your question!

Best of luck!

Solution 2

The approaches that I'd follow, from most to least preferable:

  • In ListView.ItemContainerStyle, use a DataTrigger to set Visibility based on a bound property.
  • Use a style in the ItemTemplate, or in the DataTemplate for the items if you're getting default templates from the resource dictionary.
  • Set the ItemsSource for the ListView to a CollectionView, and handle the CollectionView's Filter event in code-behind. See MSDN's discussion of collection views for details.
  • Maintain a separate ObservableCollection as the ItemsSource for the ListView and add/remove items as appropriate.

Under no circumstances would I use a ValueConverter, because I have a possibly-irrational distaste for them.

I think that using a CollectionView is probably the most correct way of doing this, but they're kind of inelegant because you have to write an event handler to implement filtering.

Solution 3

Use a style with a trigger to set the items visibility to collapsed.

Solution 4

This page gave me the answer I needed: http://www.abhisheksur.com/2010/08/woring-with-icollectionviewsource-in.html (See section "Filtering".)

Wow, so much easier than XAML.

Example:

bool myFilter(object obj)
{
    // Param 'obj' comes from your ObservableCollection<T>.
    MyClass c = obj as MyClass;
    return c.MyFilterTest();
}

// apply it
myListView.Items.Filter = myFilter;
// clear it
myListView.Items.Filter = null;
Share:
13,831

Related videos on Youtube

Admin
Author by

Admin

Updated on June 04, 2022

Comments

  • Admin
    Admin almost 2 years

    How can I hide a ListViewItem in a bound ListView? Note: I do not want to remove it.

    • Jerry Nixon
      Jerry Nixon over 12 years
      Remember to mark the right answer.
  • Y.Yanavichus
    Y.Yanavichus about 13 years
    May be you should use DataTrigger
  • Robert Rossney
    Robert Rossney over 12 years
    This won't work dynamically unless you've implemented INotifyPropertyChanged in the User class and raise PropertyChange when IsSupposedToShow changes. (Also, I'd name that property IsVisible.)
  • Jerry Nixon
    Jerry Nixon over 12 years
    @Robert Rossney, Welp :S You are correct. I updated the code to reflect your point. I wan't really trying to write production-ready, but it was a simple thing to add to side step a follow-up question. Good catch.
  • Jerry Nixon
    Jerry Nixon over 12 years
    Why didn't a style trigger in the DataTemplate make your list? It seems to be the most simple approach.
  • Robert Rossney
    Robert Rossney over 12 years
    It did! It's the second item. I tend to prefer using ItemContainerStyle by default. It's just as simple, and it also means that the behavior is localized to the ListView. This can be an important distinction when the DataTemplate isn't defined locally to the ListView.
  • Jerry Nixon
    Jerry Nixon over 12 years
    Yes, I see your point and agree. But, a style defined in the datatemplate for an itemtemplate is also local, to pick nits. But if the datatemplate is pushed up into Resources, then you have a very valid point.
  • River-Claire Williamson
    River-Claire Williamson almost 10 years
    I feel like I've missed something. The XAML makes the text of the item vanish, but not the item in the list.
  • MickyD
    MickyD over 3 years
    I like your writing style, it is very welcoming. Good answer too! +1
  • Nathan Evans
    Nathan Evans over 2 years
    I originally tried a DataTemplate DataTrigger, and it removed the content from my ListViewItem but left the item (empty but taking a small amount of space) behind. Putting the DataTrigger in ListView.ItemContainerStyle (as described in this answer) worked as needed.