2

I'm developing an App for Windows Phone 8.1. In that App I want to bind the Items of an ObservableCollection<DisruptionDisplayElement> to a ListView. DisruptionDisplayElement has a property named bool IsFavorite. In the ListView I want to hide all items, where IsFavorite is false. If I do it by using ItemContainerStyle and set the Visibility-Property to collapsed by using a Converter, it is not working. If I define the Backgroundcolor the same way for testing, it works. I can also hide the Grid, where everything of the ListViewItem is in, but in that case I still have the the decoration of the ListViewItem, that takes round about 50 pixels of space.

Here is what I've got:

XAML:

<Page
    x:Class="myApp.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:myApp"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:converter="using:myApp.Converter"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
    >
    <Page.Resources>            
        <converter:BoolToVisibilityConverter x:Key="BoolToVisibilityConv"/>
    </Page.Resources>
    <Grid>
        <Hub Header="{Binding CityName}" 
             SectionsInViewChanged="Hub_SectionsInViewChanged" 
             Grid.Row="1"
             >
             <HubSection Header="My Lines" Name="hubFavorites">
                 <DataTemplate>
                     <Grid Margin="0,-25,0,0">
                         <ListView 
                             ItemsSource="{Binding DisruptionDisplayList}"
                             Grid.Row="1"
                             >
                             <ListView.ItemContainerStyle>
                         <Style TargetType="ListViewItem">
                                     <!-- This seems not to work -->
                                     <Setter Property="Visibility" Value="{Binding IsFavorite, Converter={StaticResource BoolToVisibilityConv}}"/>
                                     <!-- For testing -->
                                     <Setter Property="Background" Value="Aqua"/>
                                 </Style>
                             </ListView.ItemContainerStyle>
                             <ListView.ItemTemplate>
                                 <DataTemplate>
                                     <!-- The Visibility-Property is just for testing as described -->
                                     <Grid 
                                         Margin="0,0,0,10" 
                                         Visibility="{Binding IsFavorite, Converter={StaticResource BoolToVisibilityConv}}"
                                         >
                                         <!-- Content here -->
                                         <TextBlock Text="{Binding Message}"/>
                                      </Grid>
                                 </DataTemplate>
                              </ListView.ItemTemplate>
                         </ListView>
                     </Grid>
                </DataTemplate>
            </HubSection>
        </Hub>
    </Grid>
</Page>

The Converter:

namespace myApp.Converter
{
    public class BoolToVisibilityConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, string culture)
        {
            return (bool) value ? Visibility.Visible : Visibility.Collapsed;
        }

        public object ConvertBack(object value, Type targetType, object parameter, string culture)
        {
            throw new NotImplementedException();
        }
    }
}

DisruptionDisplayElement:

public class DisruptionDisplayElement
{
    public string Message { get; set; }

    public bool IsFavorite { get; set; }
}

Code Behind:

namespace myApp
{
    public sealed partial class MainPage
    {
        public MainPage()
        {
            InitializeComponent();

            DataContext = new ViewModel;
        }
    }
}

My "ViewModel"-Class:

namespace myApp
{
    public class ViewModel
    {
        public ObserverableCollection<DisruptionDisplayElement> DisruptionDisplayList {get;set;}

        public ViewModel()
        {
            DisruptionDisplayList = new ObservableCollection<DisruptionDisplayElement>();
            DisruptionDisplayList.Add(new DisruptionDisplayElement() { IsFavorite = true, Message = "Message 1"});
            DisruptionDisplayList.Add(new DisruptionDisplayElement() { IsFavorite = false, Message = "Message 2" });
            DisruptionDisplayList.Add(new DisruptionDisplayElement() { IsFavorite = true, Message = "Message 3" });
        }
    }
}

What can I do to hide the ListViewItem without wasting all the space for emtpy ListViewItems if I hide the grid inside?

Edit: Advanced the Code providing

Hunv
  • 385
  • 7
  • 17

2 Answers2

0

Without a good, minimal, complete code example, it's not possible to provide an actual code example that shows the correct technique in your exact scenario.

However, the basic answer is that you should be using ICollectionView to filter the visual presentation based on some property.

There are a variety of ways to go about doing this. One of the simplest is to apply the filtering to the default view for your data source. Such a view always exists, and if you are only binding your data source to a single visual object, or you want all visual objects that present that data source to be filtered in the same way, then getting and modifying this view is the correct approach.

As an example:

ICollectionView view = CollectionViewSource.GetDefaultView(DisruptionDisplayList);

view.Filter = item => ((MyClass)item).IsFavorite;

You would configure this view in your code-behind at the appropriate time, e.g. when the user indicates through whatever input mechanism you've provided that they want to show only the favorite items.

Note that this approach avoids altogether trying to use the DataTemplate as the mechanism for showing or hiding the items. Instead, the items are filtered before they ever reach the ListView object.

Community
  • 1
  • 1
Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
  • Hi Peter, thanks for your answer. Unfortunately CollectionViewSource.GetDefaultView is not provided on Windows Phone: [link](https://msdn.microsoft.com/en-us/library/system.windows.data.collectionviewsource.getdefaultview%28v=vs.110%29.aspx ). I found no way to get use the filters under Windows Phone. So I tried it with the Visibility-Option. The result I mentioned above. I advanced my code in my first thread. – Hunv May 09 '15 at 09:00
  • 1
    Your question is tagged with WPF. If you are not using WPF, you should not use the WPF tag. Please see [my answer to a similar question](http://stackoverflow.com/a/30042113/3538012) for advice on how to accomplish the filtering behavior in the Winrt API. – Peter Duniho May 09 '15 at 15:51
  • OK, thanks. I did't thought about, that WPF is not WinRT, but it makes sense. But back to topic: Your solution in the linked post works like a charm! Thanks! – Hunv May 10 '15 at 10:01
0

if you are looking for UWP, just set MinHeight Property to 0 (zero):

<ListView.ItemContainerStyle>
     <Style TargetType="ListViewItem">
          <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
          <Setter Property="MinHeight" Value="0" />

     </Style>
</ListView.ItemContainerStyle>