【问题标题】:Prevent Listbox from display partial Listboxitem防止 Listbox 显示部分 Listboxitem
【发布时间】:2015-01-27 00:32:34
【问题描述】:

我有一个显示信息的非交互式 UI。信息保存在带有自定义 listboxitem 控件的 Listbox 控件中。

每个列表框的大小可以变化,窗口可以根据用户的需要调整大小。

我想阻止显示在应用程序中部分显示的列表框项,这将始终是最后一行。但是,如果我调整 UI 的大小,“最后一行”将会改变。

我一直在尝试this SO answer,但没有任何运气。

protected override Size ArrangeOverride(Size finalSize)
        {
        // Arrange in a stack
            double curX = 0;
            double curY = 0;
            foreach (UIElement child in InternalChildren)
            {
                double nextY = curY + child.DesiredSize.Height;
                if (nextY > finalSize.Height)         // Don't display partial items
                    child.Arrange(new Rect());
                else
                    child.Arrange(new Rect(curX, curY, child.DesiredSize.Width, child.DesiredSize.Height));
                curY = nextY;
            }

            return finalSize;

        }

“InternalChildren”我假设是我的列表框,但列表框不可枚举。我不知道如何使用这个例子。

我怎样才能达到预期的效果?

主控制

<UserControl x:Class="Cis.CustomControls.CisDeparturesPanel"
             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:customControls="clr-namespace:Cis.CustomControls"
             mc:Ignorable="d" d:DesignHeight="600" d:DesignWidth="800">
    <UserControl.Resources>
        <DataTemplate x:Key="DataTemplate">

            <ListBoxItem Padding="0"  >
                <customControls:CisDeparturesRow />
            </ListBoxItem>

        </DataTemplate>
    </UserControl.Resources>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="48"/>
            <RowDefinition Height="44"/>
            <RowDefinition Height="229*"/>
            <RowDefinition Height="279*" />
        </Grid.RowDefinitions>


        <ListBox Grid.Row="2" HorizontalContentAlignment="Stretch" Name="ListBoxDepart" Background="Black" Margin="1,0,-1,0" BorderThickness="0" ItemsSource="{Binding Path=StationMovementList}" ItemTemplate="{StaticResource DataTemplate}" ScrollViewer.VerticalScrollBarVisibility="Hidden" ScrollViewer.HorizontalScrollBarVisibility="Hidden" Grid.RowSpan="2">
            <ListBox.ItemContainerStyle>
                <Style TargetType="{x:Type ListBoxItem}">
                    <Setter Property="Focusable" Value="False"/>
                </Style>
            </ListBox.ItemContainerStyle>

        </ListBox>


    </Grid>
</UserControl>

ListBoxItem 自定义控件

<UserControl x:Class="Cis.CustomControls.CisDeparturesRow"
             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" 
             mc:Ignorable="d" d:DesignHeight="80" d:DesignWidth="800" Background="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type UserControl}}, Path=Background}" HorizontalContentAlignment="Stretch" Margin="0,0,0,0" Width="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type UserControl}}, Path=ActualWidth}">
    <UserControl.Resources>
<!-- snip --->
</UserControl.Resources>
    <Grid x:Name="ArrivalRowGrid">
        <Grid.RowDefinitions>
            <RowDefinition Height="47*"/>
            <RowDefinition Height="33*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition Width="141"/>
            <ColumnDefinition Width="117"/>
            <ColumnDefinition Width="241"/>
        </Grid.ColumnDefinitions>

        <TextBlock Name="TxtDestinationName" MouseDown="TxtDestinationName_OnMouseDown" Style="{StaticResource MainRowStyle}"  TextWrapping="Wrap" Text="{Binding Path=DestinationName,NotifyOnTargetUpdated=True, Mode=OneWay}" Margin="10,0"/>
        <TextBlock Name="TxtPlatNum" TextWrapping="Wrap" Style="{StaticResource MainRowStyle}" Text="{Binding Path=Platform,NotifyOnTargetUpdated=True, Mode=OneWay}" Margin="11,0,8,0"
                   Grid.Row="0" Grid.Column="1"/>

        <TextBlock Name="TxtArrTime" TextWrapping="Wrap" Style="{StaticResource MainRowStyle}" TextAlignment="Right" Text="{Binding Path=ExpectedDepartureTime,NotifyOnTargetUpdated=True, Mode=OneWay}" Margin="10,0,21,8"
                   Grid.Row="0" Grid.Column="3" />

        <TextBlock Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="4" x:Name="TxtCallingAt" TextWrapping="Wrap" Style="{StaticResource SubRowStyle}" TextAlignment="Left" Text="{Binding Path=CallingAt,NotifyOnTargetUpdated=True, Mode=OneWay}" Margin="10,0,21,0" />

    </Grid>
</UserControl>

【问题讨论】:

    标签: c# wpf listbox


    【解决方案1】:

    您链接到的 SO 问题包含一个 ArrangeOverride 方法,该方法用于自定义 Panel,而不是 ListBox 本身。

    一个 WPF ListBox 控件的模板,一旦展开,看起来有点像这样(当然是简化了):

    <Border>
        <ScrollViewer>
            <SomePanel>
                <ListBoxItem>your item</ListBoxItem>
                <ListBoxItem>your item</ListBoxItem>
                <ListBoxItem>your item</ListBoxItem>
                <ListBoxItem>etc</ListBoxItem>
            </SomePanel>
        </ScrollViewer>
    </Border>
    

    其中SomePanel 是派生自Panel 的类的实例。列表框的默认值是 VirtualizingStackPanel,但可以这样替换:

    <ListBox>
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                your panel type here
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
    </ListBox>
    

    您在问题中说这是针对“非交互式 UI”。这有几种不同的解释,但对我来说意味着您可以用ItemsControl 替换ListBox,因为您不需要列表框的选择能力。然后创建一个自定义面板(派生自 Panel 的类),从链接的 SO 问题中添加 ArrangeOverride 方法,并将 ItemControl 的面板替换为您的自定义面板。

    【讨论】:

    • 谢谢,我已经使用 MessureOverride 和 ArrangeOverride 创建了我的自定义面板并将其添加到我的数据模板中,但是我仍然可以看到最后一个部分项目。 (在 周围添加)您能告知为什么部分项目仍然显示吗?
    • 不确定。可能是因为默认的ListBox 控制模板包括ScrollViewer,它基本上会给子面板无限的高度来玩,因此就ArrangeOverride 方法而言,总是有足够的高度来显示所有项目.您需要能够滚动列表吗?如果没有,您可以采取不同的方法。
    • 我重新考虑了方法,我正在捕获 ItemsControl 的 Onloaded 事件并遍历每一行并计算每一行的大小并隐藏大于父容器的行。似乎工作。您的解释帮助我找到了正确的道路。谢谢。
    猜你喜欢
    • 2010-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-03
    • 1970-01-01
    • 2019-02-09
    相关资源
    最近更新 更多