不要在WPF列表框中显示部分项

不要在WPF列表框中显示部分项,wpf,listbox,Wpf,Listbox,我试过谷歌,也试过必应,但都没用。这里有人知道如何防止WPF中的列表框中出现部分项目吗?在这种情况下,这里是一个没有意义的例子:列表框是200像素高-每个项目是35像素高。这意味着我可以显示5.7项。一个项目的7/10是不可取的。我想限制它只显示5个项目。然后,用户可以滚动查看其他项目 我是否应该A)尝试动态调整listbox或ScrollViewer视口的大小,使其完全适合?或B)实施自定义面板,该面板不会安排所需高度大于剩余垂直空间的儿童 任何想法都将不胜感激。最后一点注意:如果有人知道第三

我试过谷歌,也试过必应,但都没用。这里有人知道如何防止WPF中的列表框中出现部分项目吗?在这种情况下,这里是一个没有意义的例子:列表框是200像素高-每个项目是35像素高。这意味着我可以显示5.7项。一个项目的7/10是不可取的。我想限制它只显示5个项目。然后,用户可以滚动查看其他项目

我是否应该A)尝试动态调整listbox或ScrollViewer视口的大小,使其完全适合?或B)实施自定义面板,该面板不会安排所需高度大于剩余垂直空间的儿童


任何想法都将不胜感激。最后一点注意:如果有人知道第三方控件(listbox或grid)可以执行此操作,我也会对此感兴趣。

只需在设计器中调整它的大小,直到没有部分行为止。实现一个自定义面板对于这样的东西来说是太多的工作了


您也可以尝试使用
列表视图
而不是
列表框
。我可能记错了,但我认为
列表视图不显示部分行,或者可能有不显示部分行的选项。

我今天一直在考虑这个问题,因为我的项目一直在解决这个问题。我的想法与我的项目相关,但应该适用。我假设使用MVVM ViewModel,但如果没有它,它也可以工作


将属性绑定到ListBox所在容器的高度,然后使用ValueConverter将ListBox的高度绑定到该容器的高度,以使ListBox根据单个项目的高度分阶段展开或收缩。调整大小时,这可能看起来有点滑稽,但使用一个简短的动画可以看起来很好。

您可以通过在dispather中查找列表框内容的实际高度并调整列表框的高度来实现这一点,但是,它将使列表框大小根据实现的不同而增大或缩小。

我的投票是每个项目的自定义面板。如果无法完全显示自身,则不会显示此面板。列表可以根据需要调整大小,因为它唯一的任务是成为一个可调整大小的容器,为面板提供一个区域。面板可以根据需要增减。

我的解决方案是使用一个多值转换器,将层次结构中的
列表框
滚动查看器
列表框项
以及列表框
实际高度、滚动查看器垂直偏移量作为输入,和列表框项
ActualHeight
,并返回可见性。树的最后一个(双精度)值仅用于确保转换器的
Convert
方法在任何重要值更改时被调用。基本上,如果项目的底部大于滚动查看器的底部,则返回的
可见性
隐藏
,而
可见
为其他

以下是转换器的代码:

using System;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

public class ListBoxItemToVisibilityConverter : IMultiValueConverter
{
    public object Convert(
        object[] values,
        Type targetType,
        object parameter,
        CultureInfo culture)
    {
        if ((values?.Length ?? 0) != 6)
            return Visibility.Collapsed;

        var listBox = values.OfType<ListBox>().FirstOrDefault();
        var scrollViewer = values.OfType<ScrollViewer>().FirstOrDefault();
        var listBoxItem = values.OfType<ListBoxItem>().FirstOrDefault();

        var heights = values.OfType<double>().ToArray();

        if (new object[] { listBox, scrollViewer, listBoxItem }.Any(item => item == null) || heights.Length != 3)
            return Visibility.Collapsed;

        var scrollViewerBottom = scrollViewer.PointToScreen(new Point(0, scrollViewer.ActualHeight)).Y;
        var listBoxItemBottom = listBoxItem.PointToScreen(new Point(0, listBoxItem.ActualHeight)).Y;

        return listBoxItemBottom > scrollViewerBottom ? Visibility.Hidden : Visibility.Visible;
    }

    public object[] ConvertBack(
        object value,
        Type[] targetTypes,
        object parameter,
        CultureInfo culture) =>
        throw new NotSupportedException();
}
使用系统;
利用制度全球化;
使用System.Linq;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Data;
公共类ListBoxItemToVisibilityConverter:IMultiValueConverter
{
公共对象转换(
对象[]值,
类型targetType,
对象参数,
文化信息(文化)
{
如果((值?.Length±0)!=6)
返回可见性。折叠;
var listBox=values.OfType().FirstOrDefault();
var scrollViewer=values.OfType().FirstOrDefault();
var listBoxItem=values.OfType().FirstOrDefault();
var heights=value.OfType().ToArray();
if(新对象[]{listBox,scrollViewer,listBoxItem}.Any(item=>item==null)| heights.Length!=3)
返回可见性。折叠;
var scrollViewerBottom=scrollViewer.PointToScreen(新点(0,scrollViewer.ActualHeight)).Y;
var listBoxItemBottom=listBoxItem.PointToScreen(新点(0,listBoxItem.ActualHeight)).Y;
返回listBoxItemBottom>scrollViewerBottom?可见性。隐藏:可见性。可见;
}
公共对象[]返回(
对象值,
类型[]目标类型,
对象参数,
文化信息文化)=>
抛出新的NotSupportedException();
}
其宣言:

<local:ListBoxItemToVisibilityConverter x:Key="ListBoxItemToVisibility"/>

它在项目模板中的用法:

<DataTemplate>
    <Button Content="{Binding Text}">
        <Button.Visibility>
            <MultiBinding Converter="{StaticResource ListBoxItemToVisibility}">
                <Binding RelativeSource="{RelativeSource FindAncestor, AncestorType=ListBoxItem}"/>
                <Binding RelativeSource="{RelativeSource FindAncestor, AncestorType=ScrollViewer}"/>
                <Binding RelativeSource="{RelativeSource FindAncestor, AncestorType=ListBox}"/>
                <Binding Path="ActualHeight" RelativeSource="{RelativeSource FindAncestor, AncestorType=ListBoxItem}"/>
                <Binding Path="VerticalOffset" RelativeSource="{RelativeSource FindAncestor, AncestorType=ScrollViewer}"/>
                <Binding Path="ActualHeight" RelativeSource="{RelativeSource FindAncestor, AncestorType=ListBox}"/>
            </MultiBinding>
        </Button.Visibility>
    </Button>
</DataTemplate>


我将查看列表视图。我们无法预先调整列表框的大小。当/如果用户调整窗口大小,它的高度会增加。大卫,正确处理调整大小对你很好!不这样做是我最讨厌的事。事实上,我真正的答案应该是:“不要麻烦”。您所描述的是正常的列表框行为;我怀疑你是否会因此失去任何客户。我们的列表框项目是交互式的(它们有数字上/下微调按钮)。当底部显示90%的项目时,用户尝试单击向上/向下按钮,WPF会重新定位该项目。现在,他们的鼠标位于下一项上。如果他们不知道,他们将编辑错误的项目。@David:这完全有道理。很抱歉,我做出了标准的StackOverflow行为,认为我比提问的人更清楚。根据您所描述的,我可能会使用一个自定义控件,它可以包装或继承Panel.hmmm,好吧,在WinForms中,ListBox有一个设置:IntegralHeight AFAIK,WPF ListBox没有。您能给这个答案提供更多细节吗?这个周末我将尝试提供一个简单的示例