绑定 ListView 项的可见性

Binding Visiblity of ListViewItem

我正在为 Windows Phone 8.1 开发应用程序。在该应用程序中,我想将 ObservableCollection<DisruptionDisplayElement> 的项目绑定到 ListViewDisruptionDisplayElement 有一个名为 bool IsFavorite 的 属性。在 ListView 中,我想隐藏所有项目,其中 IsFavorite 为假。 如果我使用 ItemContainerStyle 并使用转换器将 Visibility-属性 设置为折叠,则它不起作用。如果我以相同的方式定义 Backgroundcolor 进行测试,它就可以工作。 我还可以隐藏网格,ListViewItem 的所有内容都在其中,但在那种情况下,我仍然有 ListViewItem 的装饰,它占据了 space 的大约 50 个像素。

这是我得到的:

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>

转换器:

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();
        }
    }
}

中断显示元素:

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

    public bool IsFavorite { get; set; }
}

隐藏代码:

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

            DataContext = new ViewModel;
        }
    }
}

我的"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" });
        }
    }
}

如果我将网格隐藏在里面,我该怎么做才能隐藏 ListViewItem 而不会浪费空 ListViewItems 的所有 space?

编辑: 先进的代码提供

如果没有 a good, minimal, complete code example,就不可能提供实际的代码示例来展示您的具体场景中的正确技术。

但是,基本的答案是您应该使用 ICollectionView 根据一些 属性.

过滤视觉呈现

有多种方法可以做到这一点。最简单的方法之一是将筛选应用于数据源的默认视图。这样的视图总是存在的,如果你只是将你的数据源绑定到一个单一的可视化对象,或者你希望所有呈现该数据源的可视化对象以相同的方式被过滤,那么获取和修改这个视图是正确的方法.

举个例子:

ICollectionView view = CollectionViewSource.GetDefaultView(DisruptionDisplayList);

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

您可以在适当的时候在代码隐藏中配置此视图,例如当用户通过您提供的任何输入机制表示他们只想显示最喜欢的项目时。

请注意,此方法完全避免了尝试使用 DataTemplate 作为显示或隐藏项目的机制。相反,项目在到达 ListView 对象之前被过滤。

如果您正在寻找 UWP,只需将 MinHeight 属性 设置为 0(零):

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

     </Style>
</ListView.ItemContainerStyle>