当CarViewControl
的可见性设置为折叠时,它仍会显示以前的占位符(请参见下面的屏幕截图)。
有没有办法在崩溃时完全隐藏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登录到特定网站)的WebView。如果您尝试通过引用传递WebView,由于我只能假设是安全措施,您将丢失该安全令牌并且必须重新登录该站点。这就是为什么在我的情况下添加/删除ObservableCollection
中的控件不起作用的原因。
答案 0 :(得分:6)
我会说你的设计存在缺陷,但我无法解决这个问题。所以我会提供一个&#34;解决方法。&#34;
问题是你的DataTemplate
正在崩溃,这很好,但显然它所处的容器并没有崩溃。这不会发生,因为父母不会从孩子那里继承。第一个实现是每个项目都包含在ListViewItem
中,您可以通过设置ItemContainerStyle
来观察。这为您提供了两种解决方案(解决方法)。您可以在ListViewItem
上设置一些触发器,也可以像我一样轻松做事 - 如果您不介意用户界面影响。
我的完整工作申请如下。重点是您必须编辑ListViewItem
的布局/行为。在我的示例中,默认值不是BorderThickeness
而Padding
不是&#39; 0,0,0,0&#34; ...将这些设置为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分钟之后,我对此并不满意。我不满意的原因是,如果您可以访问键盘,仍然可以选择该项目。在上面的示例中,单击第一个项目,&#34;隐藏&#34;项目,然后使用鼠标,ListView.SelectedItem
仍然会改变。
以下是一个快速解决方案(解决方法:D)实际从列表中删除项目并防止它们获得焦点。将ListView.ItemContainerStyle
替换为此ActualHeight
并更改ListViewItem.DataContext
触发器值以匹配您看到的值。这将根据我认为的操作系统主题进行更改 - 我会让您接受测试。最后,请记住ItemsSource
将是DataTrigger
中项目的IsVisible
。这意味着绑定到Car.IsVisible
的{{1}}绑定到<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>
属性。
CarViewControl
编辑2 (在我发布第一次编辑之前编辑。
拧紧它,不要绑定IsTabStop
的可见性;你不需要。您只需要专注于删除项目本身,一旦项目被删除,包含的控件也将被删除(尽管您应该自己进行测试,如果仍然可以更改IsFocusable
和CarViewControl
选项卡到ActualHeight
)中的项目。此外,由于使用IsVisible
绑定的任意数字并非非常安全,因此只需直接绑定到HideCar
属性(或在您的情况下为ListViewItem
)并触发可见性<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>
就足够了。
最后,这是我的最终XAML:
shuffle
答案 1 :(得分:3)
我不会尝试通过UI隐藏项目,而是从ViewSource绑定的View或Collection中删除该项目。这是一种更清洁的方法,UI永远不必关心项目的可见性。
编辑1
当用户从快速选择菜单中选择特定的汽车时,它会显示该汽车并隐藏其他汽车。
有道理;让我们调用该视图&#34; UserCars&#34;,并假设ItemsSource绑定到UserCars。
这个怎么样:将ItemsSource更改为绑定到&#34; SelectedCollection&#34;。如果要显示UserCars,请将SelectedCollection指向UserCars集合。
要限制集合,您只需将SelectedCollection指向仅使用UserCars填充的新SingleCar.SelectedItem
<强> XAML:强>
<ListView ItemsSource="{Binding SelectedCollection}" SelectedItem="{Binding SelectedCar}">
<强>视图模型:强>
private Car _selectedCar;
public Car SelectedCar {
get { return _selectedCar; }
set { _selectedCar = value; OnPropertyChanged("SelectedCar"); }
}
private ObservableCollection<Car> _selectedCollection = CarVM.UserCars;
private ObservableCollection<Car> SelectedCollection {
get { return _selectedCollection; }
set { _selectedCollection = value; OnPropertyChanged("SelectedCollection"); }
}
private ObservableCollection<Car> _originalCollectionForReferenceKeepingOnly;
// called via RelayCommand
public void UserJustSelectedACar()
{
ObservableCollection<Car> singleItemCollection = new ObservableCollection<Car>();
singleItemCollection.Add(SelectedCar);
_originalCollectionForReferenceKeepingOnly = SelectedCollection;
SelectedCollection = singleItemCollection;
}
public void ReturnToFullUsedCarsList()
{
SelectedCollection = _originalCollectionForReferenceKeepingOnly;
}
编辑2
看来你正试图让ListView假装成一个&#34; Car Details&#34;通过隐藏这些其他项来查看。这本质上是一个坏主意;绑定到Listview的选定Car
项的不同UI元素将提供更好的解决方案。由于新的详细信息面板只是查看已生成的Car
实例,因此您不会遇到任何数据。即使你现在能够采用这种方法,我也很担心你将来会让自己更加悲伤。