防止WPF控件超出可视区域扩展

26

我在我的用户控件中有一个ItemsControl,当它变得太大时(太大意味着内容大于UserControl的可视区域),它周围有一个滚动查看器。问题是,包含它的网格只会不断扩展,以至于滚动视图器永远不会启动(除非我为网格指定一个确切的高度)。请参见下面的代码,提前致谢。

 <UserControl  x:Class="BusinessObjectCreationWizard.View.TableSelectionPageView"
               xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
               xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <GroupBox FontWeight="Bold" Height="300px"
              Header="Tables"
              Padding="2">

        <ScrollViewer>

            <ItemsControl FontWeight="Normal" 
                          ItemsSource="{Binding Path=AvailableTables}">
                <ItemsControl.ItemTemplate>

                    <DataTemplate>              
                        <CheckBox Content="{Binding Path=DisplayName}"
                                  IsChecked="{Binding Path=IsSelected}"
                                  Margin="2,3.5" /> 
                    </DataTemplate> 
                </ItemsControl.ItemTemplate> 
            </ItemsControl>
        </ScrollViewer>
    </GroupBox>
</UserControl>

这个用户控件在这里加载

<Border Background="White" Grid.Column="1" Grid.Row="0">
        <HeaderedContentControl Content="{Binding Path=CurrentPage}" 
                                Header="{Binding Path=CurrentPage.DisplayName}" />
</Border>

我不想指定高度。


网格的扩展取决于它所包含的内容。您需要展示更多的XAML以获得准确的答案。 - John Bowen
我添加了额外的代码(尽管格式有点奇怪) - Dan dot net
7个回答

29
如果您从GroupBox中删除Height(据我所知,这就是您想要做的),那么它将填充其容器,除非有一个上游面板施加自己的大小规则。我使用了这个简化版本的XAML。我删除了模板和绑定,并硬编码了一些项目,使其独立存在;这些更改不会影响布局方式。
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
    <GroupBox FontWeight="Bold" Header="Tables" Padding="2">
        <ScrollViewer>
            <ItemsControl FontWeight="Normal">
                <TextBlock>Foo</TextBlock>
                <TextBlock>Bar</TextBlock>
                <TextBlock>Baz</TextBlock>
            </ItemsControl>
        </ScrollViewer>
    </GroupBox>
</Window>

运行它,你会发现内容确实会自适应窗口大小,并且滚动条只在窗口变得太小而无法看到所有三个项时才启用。我相信这就是你想要的。

因此,问题很可能是父面板中的一个问题,其中一个你在示例XAML中没有显示。如果你的GroupBox出现在StackPanel内部,则可能会出现你描述的问题:

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
    <StackPanel>
        <GroupBox FontWeight="Bold" Header="Tables" Padding="2">
            <ScrollViewer>
                <ItemsControl FontWeight="Normal">
                    <TextBlock>Foo</TextBlock>
                    <TextBlock>Bar</TextBlock>
                    <TextBlock>Baz</TextBlock>
                </ItemsControl>
            </ScrollViewer>
        </GroupBox>
    </StackPanel>
</Window>
现在,GroupBox出现在窗口的顶部,并被调整大小以完全适应其内容。如果你缩小窗口足够多,GroupBox将被切掉-因为它被调整大小以适应其内容,而不是其容器。这听起来像是你所描述的问题。
原因是StackPanel会询问其子项的理想高度(基于其内容),并使用该高度。如果没有StackPanel(或类似的东西),则默认情况下会尊重控件的VerticalAlignment属性,如果将其设置为Stretch的默认值,则控件将被拉伸以填充其父级。这意味着它不会比其父级更高,这似乎是你想要的。
解决方案:去除StackPanel(或其他导致问题的东西)并使用其他东西。根据你想要实现的目标,使用DockPanel或Grid可能会更好。如果不了解布局的更多信息,则很难确定。
编辑:好的,看起来问题确实是HeaderedContentControl父控件--但不是直接的。HeaderedContentControl不是一个面板,因此它本身不做任何布局(它的后代GroupBox没有这个问题)。问题在于其默认模板--其中包括一个StackPanel。好消息是,你可以自由地使用不同的模板,例如一个带有DockPanel的模板:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <HeaderedContentControl>
    <HeaderedContentControl.Style>
      <Style TargetType="{x:Type HeaderedContentControl}">
        <Setter Property="Template">
          <Setter.Value>
            <ControlTemplate TargetType="{x:Type HeaderedContentControl}">
              <DockPanel>
                <ContentPresenter ContentSource="Header" DockPanel.Dock="Top"/>
                <ContentPresenter/>
              </DockPanel>
            </ControlTemplate>
          </Setter.Value>
        </Setter>
      </Style>
    </HeaderedContentControl.Style>
    <GroupBox FontWeight="Bold" Header="Tables" Padding="2">
      <ScrollViewer>
        <ItemsControl FontWeight="Normal">
          <TextBlock>Foo</TextBlock>
          <TextBlock>Bar</TextBlock>
          <TextBlock>Baz</TextBlock>
        </ItemsControl>
      </ScrollViewer>
    </GroupBox>
  </HeaderedContentControl>
</Window>
如果省略 <HeaderedContentControl.Style> 部分,会重现您的问题;但是如果使用该样式,则允许 GroupBox 填充其容器,因此当需要时 ScrollViewer 将获得滚动条。

GroupBox的父级控件(除了UserControl之外)是HeaderedContentControl。即使我明确限制它的大小,问题仍然存在。但是您的解释是最好的。感谢您花费时间。 - Dan dot net
谢谢更新。这解决了问题。由于删除StackPanel会产生其他影响,我不得不进行一些其他更改。 - Dan dot net

11

如果之前的回答不能解决问题,你也可以尝试将网格的宽度和高度绑定到父UserControl的实际宽度和高度上。类似这样:

<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="WpfApplication.UserControl1"
x:Name="UserControl">
<Grid Height="{Binding ElementName=UserControl, Path=ActualHeight}"
      Width="{Binding ElementName=UserControl, Path=ActualWidth}" />
在这种情况下,您没有设置显式的宽度和高度,但是您正在限制 Grid 的宽度/高度为其所在的 UserControl 的约束。

4

我曾经遇到同样的问题,看了这个回答后,我把UserControl中所有的StackPanels都替换成了Grids。这解决了滚动条的问题。


0

我在使用ListBox时遇到了同样的问题,它无法扩展并且滚动条也没有出现。我解决了这个问题,方法如下:

 <UserControl x:Class="TesteView" 
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
      <Grid MaxHeight="710">
      ....
      ....
      <StackPanel>
         <ListBox  MaxHeight="515" 
            ScrollViewer.HorizontalScrollBarVisibility="Hidden" 
            ScrollViewer.VerticalScrollBarVisibility="Auto" 
            ItemsSource="{Binding Path=Teste,Mode=TwoWay}">
            ....
            ....
        </ListBox>
     </StackPanel>
    </Grid>
   </UserControl>

0

它们是不同的。如果您不想让项目可选择,则不要使用ListBox。它会更重,每次用户单击条目时还必须取消选择。只需将ItemsControl放在ScrollViewer中即可。


0

尝试完全删除网格,并直接在GroupBox上设置HorizontalAlignment和VerticalAlignment。如果一个布局面板只有一个子元素,通常是多余的...这可能适用于您的情况。

如果这不起作用...您的网格控件的父级是什么?


移除网格并没有改变任何东西(但我还是移除了它,因为它是多余的)。网格的父级是一个用户控件,作为带标题内容控件的内容加载。我暂时限制了带标题内容控件的高度,以查看是否正在扩展,但这也没有解决问题。我也尝试了下面“softwarequestioneer”的建议,但没有成功。 - Dan dot net

0
为什么不使用具有内置滚动条的列表框而不是项控件呢?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接