Listview + Expander中的Listview溢出外容器
Listview in Listview + Expander spilling out of outer container
所以我有一个在列表视图中包含列表视图的扩展器,这是一个架构:
Xaml:
<UserControl x:Class="Sesam.Resources.CommonControls.FilterPanelView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Sesam.Resources.CommonControls"
xmlns:filters="clr-namespace:Sesam.Filters"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance local:FilterPanelViewModel}">
<UserControl.Resources>
<ControlTemplate x:Key="NoScroll">
<ItemsPresenter></ItemsPresenter>
</ControlTemplate>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition x:Name="ListViewGridRowDefinition" Height="*"/>
</Grid.RowDefinitions>
<Border Grid.Row="0" Background="Transparent" BorderThickness="0,0,0,1" BorderBrush="{StaticResource myLightGrey}">
<DockPanel VerticalAlignment="Center">
<Label Content="Filtres" DockPanel.Dock="Left" Foreground="{StaticResource myDarkBlue}" FontSize="14" FontWeight="SemiBold"/>
<!-- future reset button -->
</DockPanel>
</Border>
<Grid Grid.Row="1">
<ListView BorderThickness="1" ItemsSource="{Binding FilterCollection}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Disabled" >
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid Background="Transparent">
<Expander BorderThickness="2" Style="{StaticResource SesamExpanderFiltres}" Header="{Binding Title}" Foreground="White">
<ListView BorderThickness="0" ItemsSource="{Binding Filters}" SelectedItem="{Binding SelectedFilter}" SelectedIndex="{Binding SelectedIndex}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Visible" SelectionChanged="Selector_OnSelectionChanged" VirtualizingPanel.ScrollUnit="Pixel" >
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border Height="Auto" Name="ContentBorder" BorderBrush="{StaticResource myLightGrey}" BorderThickness="0,0,0,1" Visibility="{Binding IsVisible, Converter={StaticResource BoolToCollapsed}}" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="15" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid Name="selectCol" Grid.Column="0" Background="White" />
<Label Grid.Column="1" Foreground="{StaticResource myDarkBlue}" Content="{Binding Name}" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" TargetName="selectCol" Value="{StaticResource myDarkBlue}" />
<Setter Property="BorderBrush" TargetName="ContentBorder" Value="{StaticResource myDarkBlue}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
</Expander>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
</Grid>
</Grid>
我的目标是包含 "expanders" 和列表,以便在容器网格中共享 space正确的 space):
但是当我展开其中一个扩展器时,它从第一个列表视图中溢出,正如您在此处看到的那样,第二个扩展器溢出,当然滚动条不起作用:
我希望扩展器堆叠在底部,以便它们保持可见,并且扩展器 expander/list 占用剩余的 space 并让用户使用内部滚动条滚动列表包含在扩展器中。
预期结果:
我在之前的 post 中看到了如何使用固定的网格高度来执行此操作,但我的扩展器列表绑定到一个集合,因此该解决方案对我不起作用。我已经奋斗了几个小时才让它工作,想知道外部观察者是否会看到我正在犯的错误。
您可能需要创建自定义控件并自行实现行为。我不知道 "out of box" 解决方案。
实际上,由于扩展器 header 高度从不变化(我可以将其设置为固定高度)并且我可以获得 grid.row "actualheight" 并且我需要所有其他扩展器打开时折叠我在后面的代码中这样做了:
private void Expander_Expanded(object sender, RoutedEventArgs e)
{
var exp = sender as Expander;
if (exp != null)
{
exp.MaxHeight = ListViewGridRowDefinition.ActualHeight - (ContainerListView.Items.Count*31) + 28;
}
}
private void Expander_Collapsed(object sender, RoutedEventArgs e)
{
var exp = sender as Expander;
if (exp != null)
{
exp.MaxHeight = 31;
}
}
在 xaml 中:
<Expander Height="Auto" IsExpanded="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListViewItem}}}".....
同时为了解决使用此解决方案产生的副作用(容器滚动仍然启用),我将模板应用于容器列表视图以删除滚动行为:
<UserControl.Resources>
<ControlTemplate x:Key="NoScroll">
<ItemsPresenter></ItemsPresenter>
</ControlTemplate>
</UserControl.Resources>
...
<ListView x:Name="ContainerListView" Template="{StaticResource NoScroll}"
我正在使用 mvvm 模式,但我认为这是纯界面交互,因此模型不需要知道这一点,它在代码隐藏中很好。它将适用于我的应用程序中的所有进一步用途。对于 "allround" 重用自定义控件是一个很好的解决方案,但我使用 IMO 的工作量太大了。
所以我有一个在列表视图中包含列表视图的扩展器,这是一个架构:
Xaml:
<UserControl x:Class="Sesam.Resources.CommonControls.FilterPanelView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Sesam.Resources.CommonControls"
xmlns:filters="clr-namespace:Sesam.Filters"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance local:FilterPanelViewModel}">
<UserControl.Resources>
<ControlTemplate x:Key="NoScroll">
<ItemsPresenter></ItemsPresenter>
</ControlTemplate>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition x:Name="ListViewGridRowDefinition" Height="*"/>
</Grid.RowDefinitions>
<Border Grid.Row="0" Background="Transparent" BorderThickness="0,0,0,1" BorderBrush="{StaticResource myLightGrey}">
<DockPanel VerticalAlignment="Center">
<Label Content="Filtres" DockPanel.Dock="Left" Foreground="{StaticResource myDarkBlue}" FontSize="14" FontWeight="SemiBold"/>
<!-- future reset button -->
</DockPanel>
</Border>
<Grid Grid.Row="1">
<ListView BorderThickness="1" ItemsSource="{Binding FilterCollection}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Disabled" >
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid Background="Transparent">
<Expander BorderThickness="2" Style="{StaticResource SesamExpanderFiltres}" Header="{Binding Title}" Foreground="White">
<ListView BorderThickness="0" ItemsSource="{Binding Filters}" SelectedItem="{Binding SelectedFilter}" SelectedIndex="{Binding SelectedIndex}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Visible" SelectionChanged="Selector_OnSelectionChanged" VirtualizingPanel.ScrollUnit="Pixel" >
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border Height="Auto" Name="ContentBorder" BorderBrush="{StaticResource myLightGrey}" BorderThickness="0,0,0,1" Visibility="{Binding IsVisible, Converter={StaticResource BoolToCollapsed}}" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="15" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid Name="selectCol" Grid.Column="0" Background="White" />
<Label Grid.Column="1" Foreground="{StaticResource myDarkBlue}" Content="{Binding Name}" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" TargetName="selectCol" Value="{StaticResource myDarkBlue}" />
<Setter Property="BorderBrush" TargetName="ContentBorder" Value="{StaticResource myDarkBlue}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
</Expander>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
</Grid>
</Grid>
我的目标是包含 "expanders" 和列表,以便在容器网格中共享 space正确的 space):
但是当我展开其中一个扩展器时,它从第一个列表视图中溢出,正如您在此处看到的那样,第二个扩展器溢出,当然滚动条不起作用:
我希望扩展器堆叠在底部,以便它们保持可见,并且扩展器 expander/list 占用剩余的 space 并让用户使用内部滚动条滚动列表包含在扩展器中。
预期结果:
我在之前的 post 中看到了如何使用固定的网格高度来执行此操作,但我的扩展器列表绑定到一个集合,因此该解决方案对我不起作用。我已经奋斗了几个小时才让它工作,想知道外部观察者是否会看到我正在犯的错误。
您可能需要创建自定义控件并自行实现行为。我不知道 "out of box" 解决方案。
实际上,由于扩展器 header 高度从不变化(我可以将其设置为固定高度)并且我可以获得 grid.row "actualheight" 并且我需要所有其他扩展器打开时折叠我在后面的代码中这样做了:
private void Expander_Expanded(object sender, RoutedEventArgs e)
{
var exp = sender as Expander;
if (exp != null)
{
exp.MaxHeight = ListViewGridRowDefinition.ActualHeight - (ContainerListView.Items.Count*31) + 28;
}
}
private void Expander_Collapsed(object sender, RoutedEventArgs e)
{
var exp = sender as Expander;
if (exp != null)
{
exp.MaxHeight = 31;
}
}
在 xaml 中:
<Expander Height="Auto" IsExpanded="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListViewItem}}}".....
同时为了解决使用此解决方案产生的副作用(容器滚动仍然启用),我将模板应用于容器列表视图以删除滚动行为:
<UserControl.Resources>
<ControlTemplate x:Key="NoScroll">
<ItemsPresenter></ItemsPresenter>
</ControlTemplate>
</UserControl.Resources>
...
<ListView x:Name="ContainerListView" Template="{StaticResource NoScroll}"
我正在使用 mvvm 模式,但我认为这是纯界面交互,因此模型不需要知道这一点,它在代码隐藏中很好。它将适用于我的应用程序中的所有进一步用途。对于 "allround" 重用自定义控件是一个很好的解决方案,但我使用 IMO 的工作量太大了。