当WPF ContentControl被包含在ScrollViewer中时,宽度会增长但不会缩小。

7
我正在尝试弄清楚如何使我的ContentControl在水平方向上正确滚动(垂直方向目前没有问题)。通过“正确”,我是指我希望看到的内容在最小尺寸下会拉伸(无限扩展),同时会出现滚动条,以便内容不会在ContentControl区域后溢出。因此,这里是一个快速介绍:
主窗口的结构如下:
- 网格(2列为0.3*和0.7*) - 边框 - 网格(7行,其中一行设置为*,ContentControl位于其中) - ScrollViewer,其中包装了一个具有自动宽度的ContentControl的StackPanel(仅用于测试) ContentControl的模板:
- 网格(宽度设置为UserControl的ActualWidth,6行中有一行设置为Auto,其中放置了ItemsControl - ItemsControl,描述了DataTemplate类型的ItemTemplate,其中包含一个Grid,内部有一个DataGrid
实际问题是ContentControl随着窗口的调整而增长,但不会随着窗口大小调整而缩小。
主视图XAML(为了清晰起见而截短):
<ScrollViewer Grid.Row="5" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
        <ContentControl Grid.Row="5" Background="Transparent"  Focusable="False" Margin="0,5,0,0"
                            Content="{Binding CurrentSection}" ContentTemplateSelector="{StaticResource templateSelector}/>
</ScrollViewer>

临时的 XAML 模板(为清晰起见截短):

<Grid>
...
    <ItemsControl Grid.Row="4" ItemsSource="{Binding Data.QualifyingDistributionsDividends}" x:Name="QualifyingItemsControl">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Grid x:Name="DTLayoutGrid">
                    ...
                    <Grid Grid.Row="1" x:Name="DataLayout" Width="{Binding ElementName=DTLayoutGrid, Path=ActualWidth}" HorizontalAlignment="Stretch">
                        ...
                        <DataGrid Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="8" HorizontalScrollBarVisibility="Disabled"
                                  ItemsSource="{Binding Payments}" Style="{StaticResource DataGridStyle}" CellStyle="{StaticResource DataGridNormalCellStyle}">
                        </DataGrid>
                    </Grid>
                </Grid>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>

那么会发生什么呢?Datagrid 假定整个 DataTemplate 的宽度(或者是其底层控件被设置为 DataTemplates 大小),然后 * 列假定所有的空白空间。当您尝试调整包含此代码的整个窗口大小时,它将正确地增长,扩展 * 列,但似乎缩小没有“注册”,并保持您将其扩展到的大小,对其应用滚动条并忘记它。
我已经尝试了很多方法,例如为ItemsControl、其底层父元素如 Grid 等设置宽度,还设置了 ContentControlStackPanelScrollViewer 和其父级 Grid 的大小。我还尝试直接在 Datagrid 上使用 scrollviewer,这会产生一个癫痫般的“每秒 100 万次调整大小”的场景。我还尝试过玩弄 HorizontalAlignments
在某些情况下,我确实设法使水平滚动条正确显示,但不幸的是,这会使我的 DataGrid 的 * 列假定宽度为 Auto,而不是 Star,因此 DataGrid 开始在右侧有一个空白区域(不可接受,不幸的是...)
我知道为了使水平滚动条起作用,scrollviewer 的父级或子级需要设置宽度,我猜我无法确定我需要限制的确切位置。DataGrids 需要在主窗口中无限扩展,同时使第一列填充所有可用空间。如果您需要更多信息,请告诉我,我会很乐意回答。

将网格的宽度赋给ContentControl可以使其正确响应,但一旦达到最小尺寸,模板就会溢出且没有滚动条出现。将其设置为HorizontalAlignment="Stretch"也无效,移除ScrollViewer.CanContentScroll="False"也是如此。 - kosdos
兄弟...这太长了...我们不需要你的人生历程,只需要你程序中相关的部分 - Sheridan
详细解释问题以便人们更好地理解它是一段人生经历吗? 由于无法确定问题的来源,必须放入大量代码。我想我会缩小代码片段... - kosdos
1
请原谅我的转述…… 我只是给您提出了一些建议,以帮助您回答问题。这里的许多用户可能已经看到了您的问题有多长,并简单地转到了下一个问题。 +1 很好,您让问题更加简洁了。 - Sheridan
没关系!我在想这不是一道简单的问题,所以决定详细阐述一下情景。 - kosdos
2个回答

5
我觉得这只是可怕的StackPanel布局问题的又一个案例。这个问题一次又一次地出现,我承认当我开始学习WPF时也遇到了同样的问题。StackPanel不考虑其父级的可用大小,而其他面板(如DockPanel或Grid)会考虑。在MSDN上的How to: Choose Between StackPanel and DockPanel页面中有解释:
尽管您可以使用DockPanel或StackPanel来堆叠子元素,但两个控件并不总是产生相同的结果。例如,您放置子元素的顺序可能会影响DockPanel中子元素的大小,但不会影响StackPanel中子元素的大小。这种不同的行为发生是因为StackPanel在Double.PositiveInfinity方向上测量堆叠,然而DockPanel仅测量可用大小。
“StackPanel”应仅用于对齐多个项目,例如在可用空间不是问题的情况下对齐“Button”或其他控件。因此,解决方案应该很简单...只需从“ScrollViewer”中删除“StackPanel”。它似乎在那里也没有任何作用。

更新 >>>

再次查看后,似乎你是在说问题出现在 DataTemplate 内部,对吗?你可以通过将 ItemsControl.HorizontalContentAlignment 属性设置为 Stretch 来修复这个问题。这将确保每个项目都保持在 ItemsControl 的边界内。

我还会移除你在 Grid.Width 上的绑定,因为你不需要它...子 Grid 默认会占用父 Grid 的全部空间。如果这些方法都不起作用,那就简化你的问题。说真的,如果你遵循我在评论中给你的帮助中心链接中的建议,那么你要么解决了问题,要么能够回到这里提供一个完整但简明的示例供我们测试。


是的,我已经将那个StackPanel添加为测试,用Grid替换它似乎有类似的结果,只有在ScrollBar出现时会有1像素的微小差异,不幸的是无法缩小ContentControl的问题仍然存在。将其删除与在那里使用Grid没有任何区别。还没有尝试DockPanel,因为我个人避免使用它,但我仍然会尝试一下。在我休息后,我将尝试制作一个小的重现应用程序,看看是否能更准确地确定问题来自哪里。 - kosdos
问题出在 Grid.Width 上。不幸的是,移除它会使所有 Datagrid 中的 Star 列都变成自动大小,而这正是我一开始试图解决的问题,因为第一列需要占用所有可用的屏幕空间。 - kosdos
我已经剥离了所有的东西,并且明白了这只是一个典型的问题,即如果有任何星号宽度列,则 ScrollViewer 元素内部的 DataGrids 将无法正确运行。这就是设置 Grid.Width 的原因。我已经尝试了很多不同的解决方法,但都没有成功,我将继续寻找更好的解决方案。 - kosdos
似乎http://stackoverflow.com/a/20120082/3008444以及类似在Datagrid周围使用边框的方法,无论是否位于ContentControl内部或外部,都会产生相同的问题。 - kosdos
看起来mardok也遇到了无法缩小的同样问题。 - kosdos

0

我通过使用UniformGrid作为ItemsPanel,并将其行绑定到ItemsSource模型的计数,找到了我要寻找的行为:

<ScrollViewer>
    <ItemsControl ItemsSource="{Binding MyCollection}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <UniformGrid Rows="{Binding MyCollection.Count}" />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>

        <ItemsControl.ItemTemplate>
            <DataTemplate>
                 ...                      
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</ScrollViewer>

正如@Sheridan在上面指出的那样,似乎StackPanel引起了问题。此外,感谢https://dev59.com/z3NA5IYBdhLWcg3wNa6T#23375262指出了UniformGrid选项。

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