【问题标题】:Auto Width ListBox with a ScrollBar带有滚动条的自动宽度列表框
【发布时间】:2018-03-12 11:26:06
【问题描述】:

下面的代码和屏幕截图显示了我在下面遇到的问题。

我需要有一个宽度设置为自动的列表框,因为内容大小是可变的。但是,进入列表框的项目数量也会发生变化,因此有时需要一个 ScrollBar。问题是,根据下图,自动宽度似乎不能很好地与滚动条配合使用。我可以添加边距,但在不需要滚动条时我不希望有间隙。

我注意到只有当文本框有一个长字符串时才会出现问题,如果输入了一个短字符串/没有输入,那么滚动条会正确显示。

除了检测是否需要滚动条并动态添加边距之外,还有其他方法吗?我觉得应该有一种方法可以在我的 XAML 中实现这一点,同时仍将列表框列保持为 Width=Auto。

private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
{
    for (int i = 0; i < 200; i++)
    {
        lbxDocs.Items.Add("TESTSTRING"+i);
    }

    txtImagePath.Text =
        @"uPPvU18ijL9Tz6fqvwLsymkdxuS8h8jS9afzQ8i7LLXvrb2JO2hmPImVF5Dq5PZpdOkw2sTX9j6GeGL7IsaDuaf1ltY0MdzCRHGTZlUVkMa43meW3gavXAWMHyLPiyfGlHxuXcQOoH8ldxkYuxhVRcSJY3ZyCzlCsPjWuINTQyJCAU5hiDqroXWI8"+
        "uPPvU18ijL9Tz6fqvwLsymkdxuS8h8jS9afzQ8i7LLXvrb2JO2hmPImVF5Dq5PZpdOkw2sTX9j6GeGL7IsaDuaf1ltY0MdzCRHGTZlUVkMa43meW3gavXAWMHyLPiyfGlHxuXcQOoH8ldxkYuxhVRcSJY3ZyCzlCsPjWuINTQyJCAU5hiDqroXWI8";
}

<Window x:Class="Grid_ScrollBar.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Grid_ScrollBar"
        mc:Ignorable="d" Loaded="MainWindow_OnLoaded"
        TextOptions.TextRenderingMode="ClearType" WindowStartupLocation="CenterScreen"
        TextOptions.TextFormattingMode="Display" Height="400" Width="500">

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <TextBox Name="txtImagePath"/>

        <ListBox Name="lbxDocs" Grid.Column="1" Grid.Row="1"/>
    </Grid>
</Window>

滚动条被切断;

一旦我们点击ListBox 中较长的字符串项,宽度就会增加以显示滚动条的其余部分;

【问题讨论】:

  • 避免这种情况的一种方法是将滚动条设置为始终可见。在您的情况下这是一个选择,还是您想在不需要时隐藏它?
  • @ManfredRadlwimmer 感谢您的回复,不幸的是,如果不需要,我需要隐藏它。
  • 能否请您发布您的整个窗口 xaml?我觉得你的窗口宽度变小了,增加 50 或 100 就可以了,因为我看到你的窗口边框也被切断了。
  • 我不知道为什么,但是当我将您的第一个 RowDefinition 的“高度”属性从自动更改为固定值时,它会按预期工作......也许这是你的一个选择
  • @TobiasHoefer 这很奇怪......

标签: wpf


【解决方案1】:

问题是您告诉文本框占用所有可用空间,即列表框留下的所有空间。现在,由于列表框的第一个元素占用“较少”空间,因此 WPF 会授予它们可能的最小空间,并且不考虑滚动条大小。

当您遇到此类问题(内容大小可能非常)时,我最好的建议是不要将宽度设置为自动。取而代之的是按比例调整大小(这也将避免物理移动列以为列表框项目腾出更多空间的影响)。

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="9*"/>
        <ColumnDefinition Width="1*" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <TextBox Name="txtImagePath" Grid.Column="0" Grid.Row="0" TextWrapping="Wrap" Margin="0,0,10,0"/>

    <ListBox Name="lbxDocs" Grid.Column="1" Grid.Row="1" />
</Grid>

您还可以添加 TextWrapping="Wrap" 以显示全文。

但是,如果您真的想将宽度保持为自动,您可以强制 wpf 使用

计算滚动条
    <ScrollViewer  Grid.Column="1" Grid.Row="1">
        <ListBox Name="lbxDocs"/>
    </ScrollViewer>

编辑:要解决滚动查看器的问题,您需要将列表框的高度设置为滚动查看器的高度,否则自动设置将不起作用:

    <ScrollViewer x:Name="test" Grid.Column="1" Grid.Row="1" VerticalScrollBarVisibility="Auto">
        <ListBox Name="lbxDocs" Height="{Binding ElementName=test, Path=ActualHeight}"/>
    </ScrollViewer>

【讨论】:

  • 由于我想将列宽保持为自动,我尝试了您的第二个解决方案。这似乎运作良好,列宽设置为列表框中最宽的项目。我注意到它不会滚动,但使用以下方法解决了这个问题; stackoverflow.com/a/16235785/1365650。我遇到的最后一个问题是,如果我设置 VerticalScrollBarVisibility="Auto" 那么无论列表框长度如何,该栏都不会出现。
  • VerticalScrollBarVisibility="Auto" 你在哪里设置的?
  • 使用Width="9*"Width="1*"你会设置90%和10%不是他想要的自动适应
  • @CelsoLívero 是的,我知道。我还在我的回答中指定了它,我还给了他将宽度保持为自动的选项
  • 根据 Tobias 的建议,当我将第一行高度设置为固定值而不是 Auto 时,滚动条的可见性会按预期工作......我一生都无法弄清楚为什么.
【解决方案2】:

尝试将滚动视图添加到您的列表视图而不更改 xaml 的其余部分

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <TextBox Name="txtImagePath"/>
        <ListBox Name="lbxDocs" 
                 Grid.Column="1" 
                 Grid.Row="1"  
                 ScrollViewer.CanContentScroll="True"
                 ScrollViewer.VerticalScrollBarVisibility="Auto"
                 ScrollViewer.HorizontalScrollBarVisibility="Auto"
        />

Width = "*" 表示您将使用所有剩余的可用空间。 Width = "Auto" 表示您将调整内容的大小,以使所有内容都适合而不超出任何多余的空间

因此(如您所做的那样)窗口中的第 1 列将调整为列表视图的大小,第 0 列将调整为窗口的其余部分。

【讨论】:

  • 感谢您的回复。这似乎会导致完全相同的行为,请参见屏幕截图; ibb.co/dhOWV7
猜你喜欢
  • 2017-09-23
  • 2017-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-27
  • 1970-01-01
  • 2015-05-16
  • 2012-11-17
相关资源
最近更新 更多