使 Scrollviewer 填充 DockPanel 中的可用空间

Posted

技术标签:

【中文标题】使 Scrollviewer 填充 DockPanel 中的可用空间【英文标题】:Making a Scrollviewer fill the available space in a DockPanel 【发布时间】:2016-12-02 17:17:58 【问题描述】:

我有点像 WPF 菜鸟,并且正在使用 DockPanel 在 ScrollViewer 的 TextBox 中显示电子邮件的文本内容。该面板顶部有一个按钮栏和电子邮件标题区域,底部有一个按钮栏,右侧有一个面板,电子邮件本身应该动态填充剩余空间:

[顶部的横幅,下方是按钮栏和带有电子邮件标题的框。底部是另一个全宽按钮栏。它们之间的空间分为右侧的固定宽度面板和用于电子邮件内容的大文本框。] http://rowlandsoftware.com/Screenshots/LongEmail.png

(DockPanel 位于一个网格内,该网格在最顶部提供位,并在电子邮件不可见时使用。)

问题是,如果电子邮件太短或太窄,文本框将无法填充剩余的宽度。在此屏幕截图中,您可以看到框和面板之间的一些底层内容:

[在文本框和面板之间是一个未填充的列。可以看到它下面的部分内容。] http://rowlandsoftware.com/Screenshots/TooNarrow.png

XAML 是:

<DockPanel x:Name="EmailCanvas" Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2" Visibility="Collapsed" Height="Auto">
    <DockPanel x:Name="topButtonBar" DockPanel.Dock="Top" Height="50" Background="White">
        <Button x:Name="btnReturn" DockPanel.Dock="Left" Content="Return to List" Click="btnReturn_Click" />
        <Image Width="15" Source="Images/transparent.png" />
        <Button x:Name="btnTextToggle" Content="Plain text" Click="btnTextToggle_Click" />
        <Button x:Name="btnZoomOut" Content="Zoom Out" />
        <Button x:Name="btnZoomIn" Content="Zoom In" />
        <Image Width="150" DockPanel.Dock="Right" Source="Images/transparent.png" />
        <Button x:Name="btnPrint" DockPanel.Dock="Right" Content="Print" Width="100"/>
        <Image DockPanel.Dock="Right" Source="Images/transparent.png" />
    </DockPanel>
    <StackPanel x:Name="EmailHeaders" Orientation="Horizontal" DockPanel.Dock="Top" Width="Auto" Background="Linen">
        <StackPanel Orientation="Vertical">
            <TextBlock Text="Subject:" FontSize="16" />
            <TextBlock Text="Time Sent:" FontSize="16"/>
            <TextBlock Text="Other Recipients: " FontSize="16"/>
        </StackPanel>
        <StackPanel Orientation="Vertical">
            <TextBlock x:Name="labSubject" Text="Subject:" FontSize="16" />
            <TextBlock x:Name="labDateTime" Text="Sent:" FontSize="16"/>
            <TextBlock x:Name="labSpare" Text="Other Recipients:" FontSize="14"/>
        </StackPanel>
    </StackPanel>
    <DockPanel x:Name="bottomButtonBar" DockPanel.Dock="Bottom" Height="80" >
        <Image Width="150" DockPanel.Dock="Left" Source="Images/transparent.png" />
        <Button x:Name="btnDelete" DockPanel.Dock="Left" Content="Delete" />
        <Image Width="150" Source="Images/transparent.png" />
        <Button x:Name="btnSave" Content="Save" />
        <Image Width="150" Source="Images/transparent.png" />
        <Button x:Name="btnReply" Content="Reply" />
        <Image Width="150" DockPanel.Dock="Right" Source="Images/transparent.png" />
    </DockPanel>
    <StackPanel DockPanel.Dock="Right" Orientation="Vertical" Background="White" Width="150">
        <Button x:Name="btnAttachments" Content="Attachment"/>
    </StackPanel>
    <ScrollViewer x:Name="eTextViewer" VerticalScrollBarVisibility="Auto" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch">
        <TextBox x:Name="eText" Background="White" HorizontalAlignment="Stretch" TextWrapping="Wrap" FontFamily="Verdana" FontSize="18" IsReadOnly="True" />
    </ScrollViewer>
    <!--Image Width="Auto" Height="Auto" DockPanel.Dock="Bottom" Source="Images/white.png" /-->
    <WebBrowser x:Name="ehtml" Height="Auto" DockPanel.Dock="Top" Visibility="Collapsed" />
</DockPanel>

框仅被扩展以填充可用高度,而不是宽度。 DockPanel.LastChildFill 属性的文档说,

如果您将 LastChildFill 属性设置为 true(这是默认设置),则 DockPanel 的最后一个子元素总是填充剩余空间,无论 您在最后一个子元素上设置的任何其他停靠值。

msdn.microsoft.com/en-us/library/system.windows.controls.dockpanel.lastchildfill%28v=vs.110%29.aspx

情况似乎并非如此:在我的程序中,它只是填充高度,而不是宽度。 LastFillChild=true 是默认值,但将其显式设置为 True False 并没有什么区别。

有趣的是,如果您在 ScrollViewer 上设置 DockPanel.Dock="Top",它会填充可用宽度而不是高度,从而在文本框和底部按钮栏之间显示一些底层内容。这再次与文档中的说法相反,即忽略在最后一个子元素上设置的停靠值。

将 Horizo​​ntalAlignment="Stretch" 设置为 ScrollViewer 和 TextBox 并将 Horizo​​ntalContentAlignment="Stretch" 设置为 ScrollViewer 并没有什么不同。

所以我的问题是,即使电子邮件的内容太短,如何确保文本框填满 DockPanel 中的可用空间?

更新:我刚刚注意到,如果我删除最初设置为 Visibility="Collapsed" 的 WebBrowser,那么它可以正常工作。我猜它的存在使 DockPanel 将其视为 LastChild,即使它已折叠。

但是,我需要在网络浏览器中显示电子邮件和文本框之间切换,因此无法将其删除。当它们可见时,两者都需要被视为最后一个孩子。有什么想法吗?

更新 2:所以我将滚动查看器和网络浏览器包装在另一个容器中,例如网格,即 Last Child。然后我可以在两者之间切换,但它们都填满了空间。

谢谢各位。如果不在公共场合羞辱自己,我就不会到达那里;)

【问题讨论】:

markdown中代码和文本之间需要一行空格。 【参考方案1】:

DockPanel 可以使用,但请注意折叠项。虽然文档说折叠的项目对布局没有影响,但使用 DockPanel 如果它是 LastChild 则可以。 在我的案例中,解决方案是添加另一个容器作为最后一个子容器,并将我想要在该容器之间切换的两个项目放置在该容器中。然后两者都将填充面板中的剩余空间。

【讨论】:

以上是关于使 Scrollviewer 填充 DockPanel 中的可用空间的主要内容,如果未能解决你的问题,请参考以下文章

使用Canvas使ScrollViewer在代码中顺畅滚动

每次我在 WPF 中加载时如何使 Listbox 的 ScrollViewer 滚动到顶部

如何使 WPF ScrollViewer 中键单击滚动?

WPF 自定义滑动ScrollViewer

ScrollViewer 鼠标滚轮不滚动

WPF:关于ScrollViewer中嵌套Datagrid的问题