当 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>
在上图中,有三个 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)到 IsVisible
的 DataTrigger
绑定(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
的可见性;你不需要。您只需要专注于删除项目本身,一旦项目被删除,包含的控件也将被删除(尽管您应该自己测试并更改 IsTabStop
和 IsFocusable
如果您仍然可以跳转到 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/