是否有某种方法可以将WPF多选Height
的{{1}}属性设置为项高度的倍数,类似于设置html的ListBox
属性{ {1}}元素?
我有一个业务要求不有半个项目显示在列表的底部(如果它是一个带有滚动条的长列表),并且底部没有额外的空白区域(如果这是一个显示所有项目的简短列表),但我能找到的唯一方法就是不断调整size
直到看起来正确。
(我还尝试了什么?我曾经问同事,搜索过MSDN和StackOverflow,做了一些普通的Google搜索,看看VS Intellisense在编辑代码时提供了什么。有很多关于如何设置的建议高度以适应ListBox的容器,但这与我正在尝试的相反。)
答案 0 :(得分:7)
是的,可以想象会有一种更简单的方法(单个snapToWholeElement属性)。我也找不到这个属性。
为了达到你的要求,我写了一点逻辑。基本上,在我的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>
请注意,ItemTemplate有点不重要。需要注意的一件重要事情是,我给这个项目命名 - 所以我可以在以后找到它。
在代码隐藏构造函数中,我将一些数据放在列表框中:
public MainWindow( )
{
InitializeComponent( );
this.x_list.ItemsSource = Enumerable.Range( 0, 100 );
}
接下来,我正在实现一个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;
}
我将使用以下谓词,如果我正在查找的元素是边框,并且其名称为“x”,则返回true。您应该修改此谓词以匹配ItemTemplate的根元素。
findVisualItem(
x_list,
el => { return ( el is Border ) ? ( (FrameworkElement)el ).Name == "x" : false; }
);
最后,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;
}
}
}
我还使Window实现了INotifyPropertyChanged,当列表框的项目被加载时(ListBox的Loaded事件),我为'lbHeight'属性触发了一个PropertyChanged事件。在某些时候它是必要的,但最后WPF在我已经有一个渲染的项目时获取了lbHeight属性。
您的项目在高度上可能不相同,在这种情况下,您必须将VirtualizedStackPanel中的所有项目相加。如果你有一个水平滚动条,你必须考虑它的总高度当然。但这是整体想法。你发表问题只有3个小时 - 我希望有人会得到一个更简单的答案。
答案 1 :(得分:1)
这是通过将父控件Height
属性设置为Auto
来完成的,而无需为列表框本身设置任何大小(或者还设置为自动)。
要限制列表大小,您还应指定MaxHeight
属性