0

I have a problem with my ListView. I bind the ItemsSource to my ViewModel but I want items that have a certain property set to null to be completely collapsed (as in the whole item is collapsed, not just the control that is bound the the property that might be null). I have a converter that works but the ListView still seems to reserve at least some space for items that are collapsed. This results in my ListView having ugly "holes". (Please note that the holes do not take up as much space as the visible items but they do take up some space and the "invisible" items are even clickable...)

My problem is pretty much the same as the one stated here: Not showing items with Visibility=Collapsed in Windows 8.1 GridView

The only thing that bothers me is that the OP of the linked question says, that for him it's working fine in Windows Phone but not in Windows. Well for me it's not working in Windows Phone. Any suggestions what I could do?

The Code:

    <DataTemplate x:Key="UpcomingEpisodesTemplate">
        <Grid Visibility="{Binding Upcoming, Converter={StaticResource EpisodeVisibilityConverter}}">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="110"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
             ....The rest of the template which is not important...
        </Grid>
    </DataTemplate>

Thanks!

Community
  • 1
  • 1

3 Answers3

1

I have searched for 2 days to collapse items without the remaining place holder from the container style and this seems to work (WinRT 8.1).

(Key_Up Event from TextBox)

foreach (YourType element in TheListViewZoomedIn.Items)
{
    if (!element.YourProperty.Contains(ListSearchBox.Text))
        (TheListViewZoomedIn.ContainerFromItem(element) as ListViewItem).Visibility = Visibility.Collapsed;
 }

It might not be super elegant or viable for huge lists but it does the job and offers tons of control. Just make sure to set the visibility again where you need to.

I just wanted to share this - it might help others in the future,

best regards, Stefan

Stefan S.
  • 11
  • 1
0

You could try convert whatever you binding to ItemsSource. Like this:

<ListView
    ItemsSource={Binding MyList, Converter={StaticResource MyListConverter}}>

With converter like this.

public class MyListConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        return ((IEnumerable<MyType>)value).Where(x => x.MyProperty != null);
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        return null;
    }
}

Edit with ObservableCollection.

public class MyListConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        var originalObservable = (ObservableCollection<MyType>)value;

        var collection = new ObservableCollection<MyType>();

        collection.AddRange(originalObservable.Where(x => x.MyProperty != null));

        originalObservable.CollectionChanged += delegate { collection.Clear(); collection.AddRange(originalObservable.Where(x => x.MyProperty != null)); };

        return collection;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        return null;
    }
}
kober
  • 832
  • 7
  • 13
  • What a neat little trick, didn't think of that...Thanks alot! The only problem I see with that solution/workaround is that the converter won't be called if the actual ObservableCollection (that the ListView is bound to) is altered in any way (i.e. Item added/deleted etc.). I wrote a method that sets the ItemsSource to null and then to the ObservableCollection again to force the converter to be called again. – Neuromancer Apr 28 '15 at 20:30
  • Like this the View refreshes correctly. Any idea how I can achieve the same behaviour but in a "cleaner" way? – Neuromancer Apr 28 '15 at 20:36
  • Well, you can return new ObservableCollection in converter and watch original collection (stored in "value") for changes in CollectionChanged, and update the returned collection. – kober Apr 28 '15 at 21:13
  • yes, sorry, AddRange isn't available in ObservableCollection, you can use foreach and .Add, but this solution is getting kinda weird, maybe this all could be done in ViewModel. – kober Apr 28 '15 at 22:04
  • Well, the converter thing is working very well so I guess I'm just gonna leave it like that...my workaround for the refresh isn't the best solution but it's okay for now ; ) – Neuromancer Apr 28 '15 at 22:11
0

In case if it helps, you can solve this issue with extra spaces of Collapsed ListViewItems by changing ItemContainerStyle to your custom style (edit a copy of default style) and change:-

<Setter Property="MinWidth" Value="{ThemeResource ListViewItemMinWidth}"/>
<Setter Property="MinHeight" Value="{ThemeResource ListViewItemMinHeight}"/>

To

<Setter Property="MinWidth" Value="0"/>
<Setter Property="MinHeight" Value="0"/>