c# - 当 DataTemplate 子项折叠时如何隐藏 ListView 项目占位符?

标签 c# xaml listview winrt-xaml win-universal-app

CarViewControl 的可见性设置为折叠时,它仍会在原来的位置显示一个占位符(请参见下面的屏幕截图)。

有什么方法可以在 Collapsed 时完全隐藏 ListViewItem

XAML 代码

<ScrollViewer>
    <ListView ItemsSource="{Binding CarVM.UserCars}" ShowsScrollingPlaceholders="False">
        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
            </Style>
        </ListView.ItemContainerStyle>
        <ListView.ItemTemplate>
            <DataTemplate>
                <ctrl:CarViewControl Car="{Binding}" Visibility="{Binding HideCar, Converter={ThemeResource InverseVisConverter}}" />
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</ScrollViewer>

enter image description here

在上图中,有三个 CarViewControls 已折叠,后面还有一个未折叠。一个是突出显示的。我希望它们在内容折叠时完全不可见。

我尝试过的:

  • DataTemplate 控件的高度设置为 0(只是为了查看它是否隐藏了无效的占位符
  • 根据此文档将 ShowsScrollingPlaceholders 设置为 False:MSDN ListView Placeholders

折叠要求的原因

在每个 CarViewControl 中,存在一个 WebView,其中包含一个安全 token (它维护 WebView 已登录到特定网站)。如果您尝试通过引用传递 WebView,由于我只能假设是安全措施,您将丢失该安全 token 并且必须重新登录该站点。这就是为什么在 ObservableCollection 中添加/删除控件在我的情况下不起作用。

最佳答案

我会说您的设计有缺陷,但我无法修复;所以我会提供一个“解决方法”。

问题是您的 DataTemplate 正在折叠,这很好,但显然它所在的容器不会折叠。这不会自然发生,因为 parent 不会从 child 那里继承。第一个认识是每个项目都包装在 ListViewItem 中,您可以通过设置 ItemContainerStyle 来观察。这给您留下了两个解决方案(解决方法)。您可以在 ListViewItem 上设置一些触发器,也可以像我一样做一些更简单的事情——如果您不介意 UI 影响的话。

我的完整工作申请如下。要点是您必须编辑 ListViewItem 的布局/行为。在我的示例中,默认值不是 BorderThickeness 并且 Padding 不是“0, 0, 0, 0”...将它们设置为 0 将隐藏您的项目完全。

MainWindow.xaml

<Window x:Class="CollapsingListViewItemContainers.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:CollapsingListViewItemContainers"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <BooleanToVisibilityConverter x:Key="BoolToVisConverter"></BooleanToVisibilityConverter>
    </Window.Resources>
    <Grid>
        <StackPanel>
            <Button Content="Disappear Car 3" Click="Button_Click" />
            <ListView ItemsSource="{Binding Cars}">
                <ListView.ItemContainerStyle>
                    <Style TargetType="ListViewItem">
                        <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
                        <Setter Property="MinHeight" Value="0" />
                        <Setter Property="Padding" Value="0 0 0 0" />
                    </Style>
                </ListView.ItemContainerStyle>
                <ListView.ItemTemplate>
                    <DataTemplate DataType="{x:Type local:Car}">
                        <Grid Visibility="{Binding IsVisible, Converter={StaticResource BoolToVisConverter}}">
                            <StackPanel>
                                <TextBlock Text="{Binding Name}" />
                                <TextBlock Text="{Binding Title}" />
                                <TextBlock Text="{Binding Id}" />
                            </StackPanel>
                        </Grid>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackPanel>
    </Grid>
</Window>

MainWindow.xaml.cs

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;

namespace CollapsingListViewItemContainers
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public ObservableCollection<Car> _cars = new ObservableCollection<Car>
                        {
                            new Car("Not yours", "Mine", 1),
                            new Car("Not mine", "Yours", 2),
                            new Car("Not ours", "His", 3),
                            new Car("Not ours", "Hers", 4),
                        };
        public ObservableCollection<Car> Cars
        {
            get
            {
                return _cars;
            }
        }
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Cars[2].IsVisible = !Cars[2].IsVisible;
        }
    }

    public class Car : INotifyPropertyChanged
    {
        private bool _isVisible;
        public bool IsVisible
        {
            get
            {
                return _isVisible;
            }
            set
            {
                _isVisible = value;
                NotifyPropertyChanged("IsVisible");
            }
        }
        public string Name
        {
            get; set;
        }

        public string Title
        {
            get; set;
        }

        public int Id
        {
            get; set;
        }

        public Car(string name, string title, int id)
        {
            Name = name;
            Title = title;
            Id = id;
            IsVisible = true;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public void NotifyPropertyChanged(string propertyName)
        {
            if(PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

编辑

老实说,以上是一个非常便宜的解决方案,我又考虑了 3 分钟后对它不满意。我不满意的原因是,如果您可以使用键盘,您仍然可以选择该项目。在上面的示例中,单击第一个项目,“隐藏”项目,然后使用鼠标,ListView.SelectedItem 仍会发生变化。

因此,下面是一个快速解决方案(解决方法 :D),用于实际从列表中删除该项目并防止它们获得焦点。用这个替换 ListView.ItemContainerStyle 并更改 ActualHeight 触发器值以匹配您看到的值。这将根据我相信的操作系统主题而改变——我会把它留给你来测试。最后,请记住 ListViewItem.DataContext 将成为 ItemsSource 中的项目。这意味着绑定(bind)到 IsVisibleDataTrigger 绑定(bind)到 Car.IsVisible 属性。

<ListView.ItemContainerStyle>
    <Style TargetType="ListViewItem">
        <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
        <Style.Triggers>
            <Trigger Property="ActualHeight" Value="4">
                <Setter Property="Visibility" Value="Collapsed" />
            </Trigger>
            <DataTrigger Binding="{Binding IsVisible}" Value="True">
                <Setter Property="Visibility" Value="Visible" />
            </DataTrigger>
        </Style.Triggers>
    </Style>
</ListView.ItemContainerStyle>

编辑 2(在我发布第一个编辑之前编辑。

见鬼去吧,不要绑定(bind)CarViewControl 的可见性;你不需要。您只需要专注于删除项目本身,一旦项目被删除,包含的控件也将被删除(尽管您应该自己测试并更改 IsTabStopIsFocusable 如果您仍然可以跳转到 CarViewControl 中的项目)。此外,由于在 ActualHeight 绑定(bind)中使用任意数字不是很安全,只需直接绑定(bind)到 IsVisible 属性(或 HideCar案例)并触发 ListViewItem 的可见性应该就足够了。

最后,这是我的最终 XAML:

<Window x:Class="CollapsingListViewItemContainers.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:CollapsingListViewItemContainers"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <BooleanToVisibilityConverter x:Key="BoolToVisConverter"></BooleanToVisibilityConverter>
    </Window.Resources>
    <Grid>
        <StackPanel>
            <Button Content="Disappear Car 3" Click="Button_Click" />
            <ListView ItemsSource="{Binding Cars}">
                <ListView.ItemContainerStyle>
                    <Style TargetType="ListViewItem">
                        <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding IsVisible}" Value="False">
                                <Setter Property="Visibility" Value="Collapsed" />
                            </DataTrigger>
                            <DataTrigger Binding="{Binding IsVisible}" Value="True">
                                <Setter Property="Visibility" Value="Visible" />
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </ListView.ItemContainerStyle>
                <ListView.ItemTemplate>
                    <DataTemplate DataType="{x:Type local:Car}">
                        <Grid>
                            <StackPanel>
                                <TextBlock Text="{Binding Name}" />
                                <TextBlock Text="{Binding Title}" />
                                <TextBlock Text="{Binding Id}" />
                            </StackPanel>
                        </Grid>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackPanel>
    </Grid>
</Window>

关于c# - 当 DataTemplate 子项折叠时如何隐藏 ListView 项目占位符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31768684/

相关文章:

c# - Xamarin CollectionView 与 Horizo​​ntalItemSpacing 相等的项目宽度

android - 在 ListView 中选择任何列表项时不调用 OnItemSelected 方法

c# - 将行转换为linq中的列

C# - 如何声明一个将由 if 语句内的数据库调用填充的变量?

c# - 将 Collection 绑定(bind)到 ListView,抑制对象的重复但操作 ListViewItem

java - 自定义 ListView 中的弹出菜单

Android:在 AlertDialog 内的多选 ListView 中选择项目

c# - OneDrive 上传程序不适用于教育或工作场所帐户

wpf - 将字符串定义为静态资源

c# - 如何在WPF中绘制这条路径?