【问题标题】:Prevent WPF control from expanding beyond viewable area防止 WPF 控件扩展到可视区域之外
【发布时间】:2019-04-05 02:36:10
【问题描述】:

我的用户控件中有一个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>

我不想指定高度。

【问题讨论】:

  • Grid 的扩展取决于它所包含的内容。您需要显示更多的 XAML 以获得准确的答案。
  • 我添加了额外的代码(虽然格式很奇怪)

标签: wpf xaml


【解决方案1】:

如果您从 GroupBox 中删除高度(据我所知,这是您想要做的),那么它将填充其容器,除非上游有一个面板施加其自己的大小规则。

我使用了您的 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 出现在窗口的顶部,其大小正好适合其内容。如果您将 Window 缩小到足够大,则 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>

如果您省略 &lt;HeaderedContentControl.Style&gt; 部分,这会重现您的问题;但是有了样式,它允许 GroupBox 填充它的容器,所以 ScrollViewer 会在你想要的时候得到一个滚动条。

【讨论】:

  • 组框的父级(在用户控件旁边)是一个带标题的内容控件。即使我明确限制它的大小,我仍然有这个问题。但你的解释是最好的。感谢您抽出宝贵时间。
  • 感谢您的更新。那成功了。由于删除 StackPanel 会产生其他影响,因此我必须进行一些其他更改。
【解决方案2】:

如果上一个答案不能解决问题,您还可以尝试将网格的宽度、高度绑定到父用户控件的实际宽度、实际高度。比如:

<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}" />

在这种情况下,您没有设置明确的宽度和高度,而是将网格宽度/高度限制为它所在的 UserControl 的约束。

【讨论】:

    【解决方案3】:

    我遇到了同样的问题,在阅读此回复后,我将所有 StackPanels 替换为 UserControl 中的网格。它解决了滚动条问题。

    【讨论】:

      【解决方案4】:

      尝试完全移除网格并直接在 GroupBox 上设置 Horizo​​ntalAlignment 和 VerticalAlignment。如果一个布局面板只有一个孩子,它通常是多余的......这在你的情况下可能是真的。

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

      【讨论】:

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

      为什么不直接使用列表框而不是项目控件,它具有内置的滚动查看器。

      【讨论】:

        【解决方案6】:

        它们是不同的。如果您不想让项目可选择,则不要使用 ListBox。它会变得更重,并且每次用户点击一个条目时都会取消选择一个选择。只需将 ItemsControl 放在 ScrollViewer 中

        【讨论】:

          【解决方案7】:

          我在使用 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>
          

          【讨论】:

            猜你喜欢
            • 2020-12-25
            • 1970-01-01
            • 2014-08-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-04-25
            • 2010-09-21
            • 1970-01-01
            相关资源
            最近更新 更多