WPF列表框的高度是否可以设置为其项目高度的倍数?
是否有某种方法可以将WPF multi-select列表框的Height属性设置为项目高度的倍数,类似于设置html select元素的size属性 我有一个业务要求,如果是带有滚动条的长列表,则列表底部不显示半个项目,如果是显示所有项目的短列表,则列表底部不显示额外的空白,但我能找到的唯一方法是不断调整高度,直到看起来合适为止WPF列表框的高度是否可以设置为其项目高度的倍数?,wpf,listbox,Wpf,Listbox,是否有某种方法可以将WPF multi-select列表框的Height属性设置为项目高度的倍数,类似于设置html select元素的size属性 我有一个业务要求,如果是带有滚动条的长列表,则列表底部不显示半个项目,如果是显示所有项目的短列表,则列表底部不显示额外的空白,但我能找到的唯一方法是不断调整高度,直到看起来合适为止 我还试过什么?我询问了同事们,搜索了MSDN和StackOverflow,做了一些谷歌搜索,并在编辑代码时查看了VS Intellisense提供的功能。关于如何设置高
我还试过什么?我询问了同事们,搜索了MSDN和StackOverflow,做了一些谷歌搜索,并在编辑代码时查看了VS Intellisense提供的功能。关于如何设置高度以适合ListBox的容器,有很多建议,但这与我试图做的恰恰相反。是的,可以想象有一种更简单的方法来实现这一点,即使用单个SnapToHoleElement属性。我也找不到这个地方 为了达到你的要求,我写了一点逻辑。基本上,在我的Windows对象中有一个公共属性lbHeight,它通过计算每个项目的高度来计算列表框的高度 首先,让我们来看看XAML:
<Window
x:Class="SO.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="120" SizeToContent="Height"
Title="SO Sample"
>
<StackPanel>
<ListBox x:Name="x_list" Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}, Path=lbHeight}" >
<ListBox.ItemTemplate>
<DataTemplate>
<Border x:Name="x" Background="Gray" Margin="4" Padding="3">
<TextBlock Text="{Binding}" />
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</Window>
接下来,我将实现一个findVisualItem——查找数据模板的根元素。我把这个函数做了一点泛型,所以它得到了一个谓词p,它标识这是否是我想要找到的元素:
private DependencyObject findVisualItem( DependencyObject el, Predicate<DependencyObject> p )
{
DependencyObject found = null;
if( p(el) ) {
found = el;
}
else {
int count = VisualTreeHelper.GetChildrenCount( el );
for( int i=0; i<count; ++i ) {
DependencyObject c = VisualTreeHelper.GetChild( el, i );
found = findVisualItem( c, p );
if( found != null )
break;
}
}
return found;
}
最后,lbHeight属性:
public double lbHeight
{
get {
FrameworkElement item = findVisualItem(
x_list,
el => { return ( el is Border ) ? ( (FrameworkElement)el ).Name == "x" : false; }
) as FrameworkElement;
if( item != null ) {
double h = item.ActualHeight + item.Margin.Top + item.Margin.Bottom;
return h * 12;
}
else {
return 120;
}
}
}
我还使窗口实现INotifyPropertyChanged,当列表框的项被加载到ListBox的loaded事件时,我为“lbHeight”属性触发了PropertyChanged事件。在某些情况下,这是必要的,但在结束时,WPF获取了lbHeight属性,而我已经有了一个渲染项
您的项目可能高度不同,在这种情况下,您必须将VirtualizedStackPanel中的所有项目相加。如果你有一个水平滚动条,你必须考虑它的总高度当然。但这是总体思路。您发布问题才3个小时,我希望有人能给出一个更简单的答案。是的,可以想象有一种更简单的方法来实现这一点—一个SnapToHoleElement属性。我也找不到这个地方 为了达到你的要求,我写了一点逻辑。基本上,在我的Windows对象中有一个公共属性lbHeight,它通过计算每个项目的高度来计算列表框的高度 首先,让我们来看看XAML:
<Window
x:Class="SO.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="120" SizeToContent="Height"
Title="SO Sample"
>
<StackPanel>
<ListBox x:Name="x_list" Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}, Path=lbHeight}" >
<ListBox.ItemTemplate>
<DataTemplate>
<Border x:Name="x" Background="Gray" Margin="4" Padding="3">
<TextBlock Text="{Binding}" />
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</Window>
接下来,我将实现一个findVisualItem——查找数据模板的根元素。我把这个函数做了一点泛型,所以它得到了一个谓词p,它标识这是否是我想要找到的元素:
private DependencyObject findVisualItem( DependencyObject el, Predicate<DependencyObject> p )
{
DependencyObject found = null;
if( p(el) ) {
found = el;
}
else {
int count = VisualTreeHelper.GetChildrenCount( el );
for( int i=0; i<count; ++i ) {
DependencyObject c = VisualTreeHelper.GetChild( el, i );
found = findVisualItem( c, p );
if( found != null )
break;
}
}
return found;
}
最后,lbHeight属性:
public double lbHeight
{
get {
FrameworkElement item = findVisualItem(
x_list,
el => { return ( el is Border ) ? ( (FrameworkElement)el ).Name == "x" : false; }
) as FrameworkElement;
if( item != null ) {
double h = item.ActualHeight + item.Margin.Top + item.Margin.Bottom;
return h * 12;
}
else {
return 120;
}
}
}
我还使窗口实现INotifyPropertyChanged,当列表框的项被加载到ListBox的loaded事件时,我为“lbHeight”属性触发了PropertyChanged事件。在某些情况下,这是必要的,但在结束时,WPF获取了lbHeight属性,而我已经有了一个渲染项
您的项目可能高度不同,在这种情况下,您必须将VirtualizedStackPanel中的所有项目相加。如果你有一个水平滚动条,你必须考虑它的总高度当然。但这是总体思路。您发布问题才3个小时-我希望有人能给出更简单的答案。这是通过将父控件的“高度”属性设置为“自动”来完成的,而无需将列表框本身的任何大小设置为“自动”。
要限制列表大小,还应指定MaxHeight属性,方法是将父控件的“高度”属性设置为“自动”,而不将列表框本身的大小设置为“自动”。
要限制列表大小,还应指定MaxHeight属性谢谢您的回答。不幸的是,我已经离开了使用WPF的项目很久了,我不再有工具来测试这个解决方案是否有效,所以我觉得我不能让它成为公认的答案。谢谢你的回答。不幸的是,我已经离开了使用WPF的项目很久了,我不再有工具来测试这个解决方案是否有效,所以我觉得我不能让它成为公认的答案。